@yuneta/gobj-js 7.7.2 → 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.
- package/README.md +76 -2
- package/dist/gobj-js.cjs.js +96 -25
- package/dist/gobj-js.cjs.js.map +1 -1
- package/dist/gobj-js.cjs.min.js +755 -734
- package/dist/gobj-js.cjs.min.js.map +1 -1
- package/dist/gobj-js.es.js +96 -26
- package/dist/gobj-js.es.js.map +1 -1
- package/dist/gobj-js.es.min.js +809 -787
- package/dist/gobj-js.es.min.js.map +1 -1
- package/dist/gobj-js.iife.js +96 -25
- package/dist/gobj-js.iife.js.map +1 -1
- package/dist/gobj-js.iife.min.js +806 -785
- package/dist/gobj-js.iife.min.js.map +1 -1
- package/dist/gobj-js.umd.js +96 -25
- package/dist/gobj-js.umd.js.map +1 -1
- package/dist/gobj-js.umd.min.js +1128 -1107
- package/dist/gobj-js.umd.min.js.map +1 -1
- package/package.json +2 -3
package/dist/gobj-js.umd.js
CHANGED
|
@@ -2633,6 +2633,10 @@
|
|
|
2633
2633
|
function set_log_callback(fn) {
|
|
2634
2634
|
__log_callback__ = typeof fn === "function" ? fn : null;
|
|
2635
2635
|
}
|
|
2636
|
+
var __console_output_enabled__ = true;
|
|
2637
|
+
function set_console_log_enabled(enabled) {
|
|
2638
|
+
__console_output_enabled__ = enabled ? true : false;
|
|
2639
|
+
}
|
|
2636
2640
|
var __in_log_callback__ = false;
|
|
2637
2641
|
function emit_log_callback(level, msg, hora) {
|
|
2638
2642
|
if (__log_callback__ && !__in_log_callback__) {
|
|
@@ -2678,9 +2682,10 @@
|
|
|
2678
2682
|
function log_error(format) {
|
|
2679
2683
|
let msg = format_log(format);
|
|
2680
2684
|
let hora = current_timestamp();
|
|
2681
|
-
if (f_error) if (f_error === window.console.error)
|
|
2682
|
-
|
|
2683
|
-
|
|
2685
|
+
if (f_error) if (f_error === window.console.error) {
|
|
2686
|
+
if (__console_output_enabled__) f_error("%c" + hora + " ERROR: " + String(msg), "color:red");
|
|
2687
|
+
} else {
|
|
2688
|
+
if (__console_output_enabled__) window.console.error("%c" + hora + " ERROR: " + String(msg), "color:red");
|
|
2684
2689
|
f_error(`${hora} ERROR: ${String(msg)}`);
|
|
2685
2690
|
}
|
|
2686
2691
|
emit_log_callback("error", msg, hora);
|
|
@@ -2688,9 +2693,10 @@
|
|
|
2688
2693
|
function log_warning(format) {
|
|
2689
2694
|
let msg = format_log(format);
|
|
2690
2695
|
let hora = current_timestamp();
|
|
2691
|
-
if (f_warning) if (f_warning === window.console.warn)
|
|
2692
|
-
|
|
2693
|
-
|
|
2696
|
+
if (f_warning) if (f_warning === window.console.warn) {
|
|
2697
|
+
if (__console_output_enabled__) f_warning("%c" + hora + " WARNING: " + String(msg), "color:yellow");
|
|
2698
|
+
} else {
|
|
2699
|
+
if (__console_output_enabled__) window.console.warn("%c" + hora + " WARNING: " + String(msg), "color:yellow");
|
|
2694
2700
|
f_warning(`${hora} WARNING: ${String(msg)}`);
|
|
2695
2701
|
}
|
|
2696
2702
|
emit_log_callback("warning", msg, hora);
|
|
@@ -2698,24 +2704,32 @@
|
|
|
2698
2704
|
function log_info(format) {
|
|
2699
2705
|
let msg = format_log(format);
|
|
2700
2706
|
let hora = current_timestamp();
|
|
2701
|
-
if (f_info)
|
|
2707
|
+
if (f_info) {
|
|
2708
|
+
if (__console_output_enabled__) f_info("%c" + hora + " INFO: " + String(msg), "color:cyan");
|
|
2709
|
+
}
|
|
2702
2710
|
emit_log_callback("info", msg, hora);
|
|
2703
2711
|
}
|
|
2704
2712
|
function log_debug(format) {
|
|
2705
2713
|
let msg = format_log(format);
|
|
2706
2714
|
let hora = current_timestamp();
|
|
2707
|
-
if (f_debug)
|
|
2715
|
+
if (f_debug) {
|
|
2716
|
+
if (__console_output_enabled__) f_debug("%c" + hora + " DEBUG: " + String(msg), "color:silver");
|
|
2717
|
+
}
|
|
2708
2718
|
emit_log_callback("debug", msg, hora);
|
|
2709
2719
|
}
|
|
2710
2720
|
function trace_msg(format) {
|
|
2711
2721
|
let msg = format_log(format);
|
|
2712
2722
|
let hora = current_timestamp();
|
|
2713
|
-
if (f_debug)
|
|
2723
|
+
if (f_debug) {
|
|
2724
|
+
if (__console_output_enabled__) f_debug("%c" + hora + " MSG: " + String(msg), "color:cyan");
|
|
2725
|
+
}
|
|
2714
2726
|
emit_log_callback("msg", msg, hora);
|
|
2715
2727
|
}
|
|
2716
2728
|
function trace_json(jn, msg) {
|
|
2717
|
-
if (
|
|
2718
|
-
|
|
2729
|
+
if (__console_output_enabled__) {
|
|
2730
|
+
if (msg) window.console.warn("=====> " + msg);
|
|
2731
|
+
window.console.dir(jn);
|
|
2732
|
+
}
|
|
2719
2733
|
emit_log_callback("json", jn, current_timestamp());
|
|
2720
2734
|
}
|
|
2721
2735
|
/************************************************************
|
|
@@ -3528,17 +3542,26 @@
|
|
|
3528
3542
|
}
|
|
3529
3543
|
/********************************************
|
|
3530
3544
|
* Save a local attribute
|
|
3545
|
+
*
|
|
3546
|
+
* Returns 0 on success, -1 when the value did NOT reach the store.
|
|
3547
|
+
* It used to return nothing and only console.warn, so every caller up the
|
|
3548
|
+
* chain (db_save_persistent_attrs -> gobj_save_persistent_attrs -> the app)
|
|
3549
|
+
* reported success on a store that had rejected the write: a full or blocked
|
|
3550
|
+
* localStorage (quota, private mode) silently discarded the change while the
|
|
3551
|
+
* UI showed it as saved.
|
|
3531
3552
|
********************************************/
|
|
3532
3553
|
function kw_set_local_storage_value(key, value) {
|
|
3533
|
-
if (typeof window === "undefined" || !window.localStorage) return;
|
|
3554
|
+
if (typeof window === "undefined" || !window.localStorage) return 0;
|
|
3534
3555
|
if (!key || value === void 0) {
|
|
3535
|
-
|
|
3536
|
-
return;
|
|
3556
|
+
log_error(`kw_set_local_storage_value(): invalid key or value: key=${key}`);
|
|
3557
|
+
return -1;
|
|
3537
3558
|
}
|
|
3538
3559
|
try {
|
|
3539
3560
|
window.localStorage.setItem(key, JSON.stringify(value));
|
|
3561
|
+
return 0;
|
|
3540
3562
|
} catch (e) {
|
|
3541
|
-
|
|
3563
|
+
log_error(`kw_set_local_storage_value(): cannot save "${key}" (storage full or blocked?): ${e && e.message ? e.message : e}`);
|
|
3564
|
+
return -1;
|
|
3542
3565
|
}
|
|
3543
3566
|
}
|
|
3544
3567
|
/********************************************
|
|
@@ -3625,7 +3648,7 @@
|
|
|
3625
3648
|
if (is_object(kw)) new_dict = kw;
|
|
3626
3649
|
else if (is_array(kw)) for (let i = 0; i < kw.length; i++) {
|
|
3627
3650
|
let kv = kw[i];
|
|
3628
|
-
let id = kw_get_str(kv, "id",
|
|
3651
|
+
let id = kw_get_str(gobj, kv, "id", "", 0);
|
|
3629
3652
|
if (!empty_string(id)) new_dict[id] = kv;
|
|
3630
3653
|
}
|
|
3631
3654
|
else log_error(`${gobj_short_name(gobj)} kwid_new_dict: data type unknown`);
|
|
@@ -4513,6 +4536,10 @@
|
|
|
4513
4536
|
let value = elem.getAttribute("data-i18n-aria-label");
|
|
4514
4537
|
if (value) elem.setAttribute("aria-label", t(value));
|
|
4515
4538
|
});
|
|
4539
|
+
element.querySelectorAll("[data-i18n-placeholder]").forEach(function(elem) {
|
|
4540
|
+
let value = elem.getAttribute("data-i18n-placeholder");
|
|
4541
|
+
if (value) elem.setAttribute("placeholder", t(value));
|
|
4542
|
+
});
|
|
4516
4543
|
}
|
|
4517
4544
|
/************************************************************
|
|
4518
4545
|
* Example Usage
|
|
@@ -4694,13 +4721,16 @@
|
|
|
4694
4721
|
}
|
|
4695
4722
|
}
|
|
4696
4723
|
/************************************************************
|
|
4697
|
-
*
|
|
4724
|
+
* Returns 0 on success, -1 when the attrs did NOT reach the store
|
|
4725
|
+
* (quota exceeded, private mode, storage disabled). Callers must check
|
|
4726
|
+
* it: a discarded write with a UI that shows the value as saved is the
|
|
4727
|
+
* worst of both worlds.
|
|
4698
4728
|
************************************************************/
|
|
4699
4729
|
function db_save_persistent_attrs(gobj, keys) {
|
|
4700
4730
|
let attrs = kw_clone_by_keys(gobj, gobj_read_attrs(gobj, sdata_flag_t.SDF_PERSIST, 0), keys, false);
|
|
4701
4731
|
let jn_file = kw_get_local_storage_value(_get_persistent_path(gobj), null, false);
|
|
4702
4732
|
if (jn_file && is_object(jn_file)) json_object_update_missing(attrs, jn_file);
|
|
4703
|
-
kw_set_local_storage_value(_get_persistent_path(gobj), attrs);
|
|
4733
|
+
return kw_set_local_storage_value(_get_persistent_path(gobj), attrs);
|
|
4704
4734
|
}
|
|
4705
4735
|
/************************************************************
|
|
4706
4736
|
*
|
|
@@ -4916,6 +4946,7 @@
|
|
|
4916
4946
|
* is_writable // field writable (no readonly)
|
|
4917
4947
|
* default_value
|
|
4918
4948
|
* placeholder
|
|
4949
|
+
* fkey // fkey mapping {topic_name: hook_name}, null if none
|
|
4919
4950
|
* ]
|
|
4920
4951
|
*
|
|
4921
4952
|
* The template is recursive, in values you can set dictionaries, or arrays,
|
|
@@ -4985,7 +5016,8 @@
|
|
|
4985
5016
|
is_hidden: false,
|
|
4986
5017
|
default_value: col.default,
|
|
4987
5018
|
placeholder: col.placeholder,
|
|
4988
|
-
fillspace: col.fillspace || 4
|
|
5019
|
+
fillspace: col.fillspace || 4,
|
|
5020
|
+
fkey: col.fkey || null
|
|
4989
5021
|
};
|
|
4990
5022
|
if (!col.flag) return field_desc;
|
|
4991
5023
|
for (let i = 0; i < col.flag.length; i++) {
|
|
@@ -5031,7 +5063,8 @@
|
|
|
5031
5063
|
is_writable: false,
|
|
5032
5064
|
is_hidden: false,
|
|
5033
5065
|
default_value: void 0,
|
|
5034
|
-
placeholder: void 0
|
|
5066
|
+
placeholder: void 0,
|
|
5067
|
+
fkey: null
|
|
5035
5068
|
};
|
|
5036
5069
|
if (is_string(value)) {
|
|
5037
5070
|
let values = value.split(".");
|
|
@@ -5075,7 +5108,9 @@
|
|
|
5075
5108
|
let new_record = {};
|
|
5076
5109
|
if (!kw) kw = {};
|
|
5077
5110
|
Object.entries(template).forEach(([field, col]) => {
|
|
5078
|
-
|
|
5111
|
+
let default_value;
|
|
5112
|
+
if (is_object(col)) default_value = col.default;
|
|
5113
|
+
new_record[field] = kw_get_dict_value(null, kw, field, default_value);
|
|
5079
5114
|
});
|
|
5080
5115
|
return new_record;
|
|
5081
5116
|
}
|
|
@@ -5444,7 +5479,9 @@
|
|
|
5444
5479
|
SDATA(data_type_t.DTP_STRING, "jwt", sdata_flag_t.SDF_PERSIST, "", "JWT"),
|
|
5445
5480
|
SDATA(data_type_t.DTP_STRING, "cert_pem", sdata_flag_t.SDF_PERSIST, "", "SSL server certification, PEM str format"),
|
|
5446
5481
|
SDATA(data_type_t.DTP_JSON, "extra_info", sdata_flag_t.SDF_RD, "{}", "dict data set by user, added to the identity card msg."),
|
|
5447
|
-
SDATA(data_type_t.
|
|
5482
|
+
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."),
|
|
5483
|
+
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"),
|
|
5484
|
+
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"),
|
|
5448
5485
|
SDATA(data_type_t.DTP_INTEGER, "timeout_idack", sdata_flag_t.SDF_RD, "5000", "timeout waiting idAck"),
|
|
5449
5486
|
SDATA(data_type_t.DTP_POINTER, "subscriber", 0, 0, "subscriber of output-events. If null then subscriber is the parent"),
|
|
5450
5487
|
SDATA_END()
|
|
@@ -5457,7 +5494,8 @@
|
|
|
5457
5494
|
gobj_timer: null,
|
|
5458
5495
|
inform_on_close: false,
|
|
5459
5496
|
websocket: null,
|
|
5460
|
-
inside_on_open: false
|
|
5497
|
+
inside_on_open: false,
|
|
5498
|
+
retry_ms: 0
|
|
5461
5499
|
};
|
|
5462
5500
|
var __gclass__ = null;
|
|
5463
5501
|
/******************************
|
|
@@ -5505,6 +5543,7 @@
|
|
|
5505
5543
|
function mt_start(gobj) {
|
|
5506
5544
|
let priv = gobj.priv;
|
|
5507
5545
|
gobj_start(priv.gobj_timer);
|
|
5546
|
+
priv.retry_ms = 0;
|
|
5508
5547
|
priv.websocket = setup_websocket(gobj);
|
|
5509
5548
|
return 0;
|
|
5510
5549
|
}
|
|
@@ -5763,6 +5802,8 @@
|
|
|
5763
5802
|
let yuno_version = gobj_read_str_attr(gobj_yuno(), "yuno_version");
|
|
5764
5803
|
let yuno_release = gobj_read_str_attr(gobj_yuno(), "yuno_release");
|
|
5765
5804
|
let yuno_tag = gobj_read_str_attr(gobj_yuno(), "yuno_tag");
|
|
5805
|
+
let required_services = gobj_read_attr(gobj, "required_services");
|
|
5806
|
+
if (!required_services || !required_services.length) required_services = gobj_read_attr(gobj_yuno(), "required_services");
|
|
5766
5807
|
let kw = {
|
|
5767
5808
|
"yuno_role": gobj_yuno_role(),
|
|
5768
5809
|
"yuno_id": gobj_yuno_id(),
|
|
@@ -5781,7 +5822,7 @@
|
|
|
5781
5822
|
"id": node_uuid(),
|
|
5782
5823
|
"user_agent": typeof window !== "undefined" ? window.navigator.userAgent : "",
|
|
5783
5824
|
"language": typeof window !== "undefined" ? window.navigator.language : "",
|
|
5784
|
-
"required_services":
|
|
5825
|
+
"required_services": required_services
|
|
5785
5826
|
};
|
|
5786
5827
|
msg_iev_push_stack(gobj, kw, IEVENT_STACK_ID, build_cli_ievent_request(gobj, gobj_name(gobj_parent(gobj)), null));
|
|
5787
5828
|
msg_iev_set_msg_type(gobj, kw, "__identity__");
|
|
@@ -5910,9 +5951,37 @@
|
|
|
5910
5951
|
was_clean: e.wasClean
|
|
5911
5952
|
});
|
|
5912
5953
|
}
|
|
5913
|
-
if (gobj_is_running(gobj)) set_timeout(priv.gobj_timer,
|
|
5954
|
+
if (gobj_is_running(gobj)) set_timeout(priv.gobj_timer, next_retry(gobj));
|
|
5914
5955
|
return 0;
|
|
5915
5956
|
}
|
|
5957
|
+
/***************************************************************
|
|
5958
|
+
* How long to wait before the next reconnect attempt.
|
|
5959
|
+
*
|
|
5960
|
+
* The delay used to be a constant (`timeout_retry`, 5s), for ever. A
|
|
5961
|
+
* backend that is down — or a URL with a typo, which never comes back —
|
|
5962
|
+
* was therefore hit every 5 seconds for the whole life of the tab, by
|
|
5963
|
+
* EVERY link pointed at it, all in lockstep. It backs off now: from
|
|
5964
|
+
* `timeout_retry`, doubling, capped at `timeout_retry_max`.
|
|
5965
|
+
*
|
|
5966
|
+
* The jitter (±20%) is what breaks the lockstep. Without it, N links that
|
|
5967
|
+
* went down together retry together for ever — a thundering herd against a
|
|
5968
|
+
* backend that is just coming back up. It is the one place a random number
|
|
5969
|
+
* earns its keep.
|
|
5970
|
+
*
|
|
5971
|
+
* Reset to zero when a session is actually reached
|
|
5972
|
+
* (ac_identity_card_ack), so a link that flaps once does not carry a
|
|
5973
|
+
* minute-long penalty into its next real drop.
|
|
5974
|
+
***************************************************************/
|
|
5975
|
+
function next_retry(gobj) {
|
|
5976
|
+
let priv = gobj.priv;
|
|
5977
|
+
let base = gobj_read_integer_attr(gobj, "timeout_retry");
|
|
5978
|
+
let max = gobj_read_integer_attr(gobj, "timeout_retry_max");
|
|
5979
|
+
if (max < base) max = base;
|
|
5980
|
+
priv.retry_ms = priv.retry_ms ? Math.min(priv.retry_ms * 2, max) : base;
|
|
5981
|
+
let jitter = priv.retry_ms * .2;
|
|
5982
|
+
let ms = priv.retry_ms - jitter + Math.random() * 2 * jitter;
|
|
5983
|
+
return Math.max(1, Math.round(ms));
|
|
5984
|
+
}
|
|
5916
5985
|
/********************************************
|
|
5917
5986
|
*
|
|
5918
5987
|
********************************************/
|
|
@@ -5953,6 +6022,7 @@
|
|
|
5953
6022
|
} else {
|
|
5954
6023
|
gobj_change_state(gobj, "ST_SESSION");
|
|
5955
6024
|
priv.inside_on_open = true;
|
|
6025
|
+
priv.retry_ms = 0;
|
|
5956
6026
|
if (!priv.inform_on_close) {
|
|
5957
6027
|
priv.inform_on_close = true;
|
|
5958
6028
|
let kw_on_open = {
|
|
@@ -6376,6 +6446,7 @@
|
|
|
6376
6446
|
exports.safeSrc = safeSrc;
|
|
6377
6447
|
exports.sdata_flag_t = sdata_flag_t;
|
|
6378
6448
|
exports.send_http_json_post = send_http_json_post;
|
|
6449
|
+
exports.set_console_log_enabled = set_console_log_enabled;
|
|
6379
6450
|
exports.set_log_callback = set_log_callback;
|
|
6380
6451
|
exports.set_remote_log_functions = set_remote_log_functions;
|
|
6381
6452
|
exports.set_timeout = set_timeout;
|