@yuneta/gobj-js 7.7.3 → 7.8.0

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.
@@ -2631,6 +2631,10 @@ var gobjJs = (function(exports) {
2631
2631
  function set_log_callback(fn) {
2632
2632
  __log_callback__ = typeof fn === "function" ? fn : null;
2633
2633
  }
2634
+ var __console_output_enabled__ = true;
2635
+ function set_console_log_enabled(enabled) {
2636
+ __console_output_enabled__ = enabled ? true : false;
2637
+ }
2634
2638
  var __in_log_callback__ = false;
2635
2639
  function emit_log_callback(level, msg, hora) {
2636
2640
  if (__log_callback__ && !__in_log_callback__) {
@@ -2676,9 +2680,10 @@ var gobjJs = (function(exports) {
2676
2680
  function log_error(format) {
2677
2681
  let msg = format_log(format);
2678
2682
  let hora = current_timestamp();
2679
- if (f_error) if (f_error === window.console.error) f_error("%c" + hora + " ERROR: " + String(msg), "color:red");
2680
- else {
2681
- window.console.error("%c" + hora + " ERROR: " + String(msg), "color:red");
2683
+ if (f_error) if (f_error === window.console.error) {
2684
+ if (__console_output_enabled__) f_error("%c" + hora + " ERROR: " + String(msg), "color:red");
2685
+ } else {
2686
+ if (__console_output_enabled__) window.console.error("%c" + hora + " ERROR: " + String(msg), "color:red");
2682
2687
  f_error(`${hora} ERROR: ${String(msg)}`);
2683
2688
  }
2684
2689
  emit_log_callback("error", msg, hora);
@@ -2686,9 +2691,10 @@ var gobjJs = (function(exports) {
2686
2691
  function log_warning(format) {
2687
2692
  let msg = format_log(format);
2688
2693
  let hora = current_timestamp();
2689
- if (f_warning) if (f_warning === window.console.warn) f_warning("%c" + hora + " WARNING: " + String(msg), "color:yellow");
2690
- else {
2691
- window.console.warn("%c" + hora + " WARNING: " + String(msg), "color:yellow");
2694
+ if (f_warning) if (f_warning === window.console.warn) {
2695
+ if (__console_output_enabled__) f_warning("%c" + hora + " WARNING: " + String(msg), "color:yellow");
2696
+ } else {
2697
+ if (__console_output_enabled__) window.console.warn("%c" + hora + " WARNING: " + String(msg), "color:yellow");
2692
2698
  f_warning(`${hora} WARNING: ${String(msg)}`);
2693
2699
  }
2694
2700
  emit_log_callback("warning", msg, hora);
@@ -2696,24 +2702,32 @@ var gobjJs = (function(exports) {
2696
2702
  function log_info(format) {
2697
2703
  let msg = format_log(format);
2698
2704
  let hora = current_timestamp();
2699
- if (f_info) f_info("%c" + hora + " INFO: " + String(msg), "color:cyan");
2705
+ if (f_info) {
2706
+ if (__console_output_enabled__) f_info("%c" + hora + " INFO: " + String(msg), "color:cyan");
2707
+ }
2700
2708
  emit_log_callback("info", msg, hora);
2701
2709
  }
2702
2710
  function log_debug(format) {
2703
2711
  let msg = format_log(format);
2704
2712
  let hora = current_timestamp();
2705
- if (f_debug) f_debug("%c" + hora + " DEBUG: " + String(msg), "color:silver");
2713
+ if (f_debug) {
2714
+ if (__console_output_enabled__) f_debug("%c" + hora + " DEBUG: " + String(msg), "color:silver");
2715
+ }
2706
2716
  emit_log_callback("debug", msg, hora);
2707
2717
  }
2708
2718
  function trace_msg(format) {
2709
2719
  let msg = format_log(format);
2710
2720
  let hora = current_timestamp();
2711
- if (f_debug) f_debug("%c" + hora + " MSG: " + String(msg), "color:cyan");
2721
+ if (f_debug) {
2722
+ if (__console_output_enabled__) f_debug("%c" + hora + " MSG: " + String(msg), "color:cyan");
2723
+ }
2712
2724
  emit_log_callback("msg", msg, hora);
2713
2725
  }
2714
2726
  function trace_json(jn, msg) {
2715
- if (msg) window.console.warn("=====> " + msg);
2716
- window.console.dir(jn);
2727
+ if (__console_output_enabled__) {
2728
+ if (msg) window.console.warn("=====> " + msg);
2729
+ window.console.dir(jn);
2730
+ }
2717
2731
  emit_log_callback("json", jn, current_timestamp());
2718
2732
  }
2719
2733
  /************************************************************
@@ -3526,17 +3540,26 @@ var gobjJs = (function(exports) {
3526
3540
  }
3527
3541
  /********************************************
3528
3542
  * Save a local attribute
3543
+ *
3544
+ * Returns 0 on success, -1 when the value did NOT reach the store.
3545
+ * It used to return nothing and only console.warn, so every caller up the
3546
+ * chain (db_save_persistent_attrs -> gobj_save_persistent_attrs -> the app)
3547
+ * reported success on a store that had rejected the write: a full or blocked
3548
+ * localStorage (quota, private mode) silently discarded the change while the
3549
+ * UI showed it as saved.
3529
3550
  ********************************************/
3530
3551
  function kw_set_local_storage_value(key, value) {
3531
- if (typeof window === "undefined" || !window.localStorage) return;
3552
+ if (typeof window === "undefined" || !window.localStorage) return 0;
3532
3553
  if (!key || value === void 0) {
3533
- window.console.warn(`Invalid key or value for localStorage: key=${key}, value=${value}`);
3534
- return;
3554
+ log_error(`kw_set_local_storage_value(): invalid key or value: key=${key}`);
3555
+ return -1;
3535
3556
  }
3536
3557
  try {
3537
3558
  window.localStorage.setItem(key, JSON.stringify(value));
3559
+ return 0;
3538
3560
  } catch (e) {
3539
- window.console.warn(`Error saving localStorage key "${key}":`, e);
3561
+ log_error(`kw_set_local_storage_value(): cannot save "${key}" (storage full or blocked?): ${e && e.message ? e.message : e}`);
3562
+ return -1;
3540
3563
  }
3541
3564
  }
3542
3565
  /********************************************
@@ -4511,6 +4534,10 @@ var gobjJs = (function(exports) {
4511
4534
  let value = elem.getAttribute("data-i18n-aria-label");
4512
4535
  if (value) elem.setAttribute("aria-label", t(value));
4513
4536
  });
4537
+ element.querySelectorAll("[data-i18n-placeholder]").forEach(function(elem) {
4538
+ let value = elem.getAttribute("data-i18n-placeholder");
4539
+ if (value) elem.setAttribute("placeholder", t(value));
4540
+ });
4514
4541
  }
4515
4542
  /************************************************************
4516
4543
  * Example Usage
@@ -4692,13 +4719,16 @@ var gobjJs = (function(exports) {
4692
4719
  }
4693
4720
  }
4694
4721
  /************************************************************
4695
- *
4722
+ * Returns 0 on success, -1 when the attrs did NOT reach the store
4723
+ * (quota exceeded, private mode, storage disabled). Callers must check
4724
+ * it: a discarded write with a UI that shows the value as saved is the
4725
+ * worst of both worlds.
4696
4726
  ************************************************************/
4697
4727
  function db_save_persistent_attrs(gobj, keys) {
4698
4728
  let attrs = kw_clone_by_keys(gobj, gobj_read_attrs(gobj, sdata_flag_t.SDF_PERSIST, 0), keys, false);
4699
4729
  let jn_file = kw_get_local_storage_value(_get_persistent_path(gobj), null, false);
4700
4730
  if (jn_file && is_object(jn_file)) json_object_update_missing(attrs, jn_file);
4701
- kw_set_local_storage_value(_get_persistent_path(gobj), attrs);
4731
+ return kw_set_local_storage_value(_get_persistent_path(gobj), attrs);
4702
4732
  }
4703
4733
  /************************************************************
4704
4734
  *
@@ -5447,7 +5477,9 @@ var gobjJs = (function(exports) {
5447
5477
  SDATA(data_type_t.DTP_STRING, "jwt", sdata_flag_t.SDF_PERSIST, "", "JWT"),
5448
5478
  SDATA(data_type_t.DTP_STRING, "cert_pem", sdata_flag_t.SDF_PERSIST, "", "SSL server certification, PEM str format"),
5449
5479
  SDATA(data_type_t.DTP_JSON, "extra_info", sdata_flag_t.SDF_RD, "{}", "dict data set by user, added to the identity card msg."),
5450
- SDATA(data_type_t.DTP_INTEGER, "timeout_retry", sdata_flag_t.SDF_RD, "5000", "timeout waiting idAck"),
5480
+ SDATA(data_type_t.DTP_LIST, "required_services", sdata_flag_t.SDF_RD, "[]", "Services this LINK requires (identity card). Empty = the yuno's `required_services`, as before. A yuno with several links to DIFFERENT backends must set it per link: the yuno-wide list is the union, so every backend is told the service names of all the others."),
5481
+ SDATA(data_type_t.DTP_INTEGER, "timeout_retry", sdata_flag_t.SDF_RD, "5000", "First reconnect delay (ms). It BACKS OFF from here, doubling up to timeout_retry_max, and resets when a session is reached"),
5482
+ SDATA(data_type_t.DTP_INTEGER, "timeout_retry_max", sdata_flag_t.SDF_RD, "60000", "Cap of the reconnect backoff (ms). Set it equal to timeout_retry for the old fixed-interval behaviour"),
5451
5483
  SDATA(data_type_t.DTP_INTEGER, "timeout_idack", sdata_flag_t.SDF_RD, "5000", "timeout waiting idAck"),
5452
5484
  SDATA(data_type_t.DTP_POINTER, "subscriber", 0, 0, "subscriber of output-events. If null then subscriber is the parent"),
5453
5485
  SDATA_END()
@@ -5460,7 +5492,8 @@ var gobjJs = (function(exports) {
5460
5492
  gobj_timer: null,
5461
5493
  inform_on_close: false,
5462
5494
  websocket: null,
5463
- inside_on_open: false
5495
+ inside_on_open: false,
5496
+ retry_ms: 0
5464
5497
  };
5465
5498
  var __gclass__ = null;
5466
5499
  /******************************
@@ -5508,6 +5541,7 @@ var gobjJs = (function(exports) {
5508
5541
  function mt_start(gobj) {
5509
5542
  let priv = gobj.priv;
5510
5543
  gobj_start(priv.gobj_timer);
5544
+ priv.retry_ms = 0;
5511
5545
  priv.websocket = setup_websocket(gobj);
5512
5546
  return 0;
5513
5547
  }
@@ -5766,6 +5800,8 @@ var gobjJs = (function(exports) {
5766
5800
  let yuno_version = gobj_read_str_attr(gobj_yuno(), "yuno_version");
5767
5801
  let yuno_release = gobj_read_str_attr(gobj_yuno(), "yuno_release");
5768
5802
  let yuno_tag = gobj_read_str_attr(gobj_yuno(), "yuno_tag");
5803
+ let required_services = gobj_read_attr(gobj, "required_services");
5804
+ if (!required_services || !required_services.length) required_services = gobj_read_attr(gobj_yuno(), "required_services");
5769
5805
  let kw = {
5770
5806
  "yuno_role": gobj_yuno_role(),
5771
5807
  "yuno_id": gobj_yuno_id(),
@@ -5784,7 +5820,7 @@ var gobjJs = (function(exports) {
5784
5820
  "id": node_uuid(),
5785
5821
  "user_agent": typeof window !== "undefined" ? window.navigator.userAgent : "",
5786
5822
  "language": typeof window !== "undefined" ? window.navigator.language : "",
5787
- "required_services": gobj_read_attr(gobj_yuno(), "required_services")
5823
+ "required_services": required_services
5788
5824
  };
5789
5825
  msg_iev_push_stack(gobj, kw, IEVENT_STACK_ID, build_cli_ievent_request(gobj, gobj_name(gobj_parent(gobj)), null));
5790
5826
  msg_iev_set_msg_type(gobj, kw, "__identity__");
@@ -5913,9 +5949,37 @@ var gobjJs = (function(exports) {
5913
5949
  was_clean: e.wasClean
5914
5950
  });
5915
5951
  }
5916
- if (gobj_is_running(gobj)) set_timeout(priv.gobj_timer, gobj_read_integer_attr(gobj, "timeout_retry"));
5952
+ if (gobj_is_running(gobj)) set_timeout(priv.gobj_timer, next_retry(gobj));
5917
5953
  return 0;
5918
5954
  }
5955
+ /***************************************************************
5956
+ * How long to wait before the next reconnect attempt.
5957
+ *
5958
+ * The delay used to be a constant (`timeout_retry`, 5s), for ever. A
5959
+ * backend that is down — or a URL with a typo, which never comes back —
5960
+ * was therefore hit every 5 seconds for the whole life of the tab, by
5961
+ * EVERY link pointed at it, all in lockstep. It backs off now: from
5962
+ * `timeout_retry`, doubling, capped at `timeout_retry_max`.
5963
+ *
5964
+ * The jitter (±20%) is what breaks the lockstep. Without it, N links that
5965
+ * went down together retry together for ever — a thundering herd against a
5966
+ * backend that is just coming back up. It is the one place a random number
5967
+ * earns its keep.
5968
+ *
5969
+ * Reset to zero when a session is actually reached
5970
+ * (ac_identity_card_ack), so a link that flaps once does not carry a
5971
+ * minute-long penalty into its next real drop.
5972
+ ***************************************************************/
5973
+ function next_retry(gobj) {
5974
+ let priv = gobj.priv;
5975
+ let base = gobj_read_integer_attr(gobj, "timeout_retry");
5976
+ let max = gobj_read_integer_attr(gobj, "timeout_retry_max");
5977
+ if (max < base) max = base;
5978
+ priv.retry_ms = priv.retry_ms ? Math.min(priv.retry_ms * 2, max) : base;
5979
+ let jitter = priv.retry_ms * .2;
5980
+ let ms = priv.retry_ms - jitter + Math.random() * 2 * jitter;
5981
+ return Math.max(1, Math.round(ms));
5982
+ }
5919
5983
  /********************************************
5920
5984
  *
5921
5985
  ********************************************/
@@ -5956,6 +6020,7 @@ var gobjJs = (function(exports) {
5956
6020
  } else {
5957
6021
  gobj_change_state(gobj, "ST_SESSION");
5958
6022
  priv.inside_on_open = true;
6023
+ priv.retry_ms = 0;
5959
6024
  if (!priv.inform_on_close) {
5960
6025
  priv.inform_on_close = true;
5961
6026
  let kw_on_open = {
@@ -6379,6 +6444,7 @@ var gobjJs = (function(exports) {
6379
6444
  exports.safeSrc = safeSrc;
6380
6445
  exports.sdata_flag_t = sdata_flag_t;
6381
6446
  exports.send_http_json_post = send_http_json_post;
6447
+ exports.set_console_log_enabled = set_console_log_enabled;
6382
6448
  exports.set_log_callback = set_log_callback;
6383
6449
  exports.set_remote_log_functions = set_remote_log_functions;
6384
6450
  exports.set_timeout = set_timeout;