@yuneta/gobj-js 7.26.20 → 7.26.22
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 +73 -6
- package/dist/gobj-js.cjs.js +1137 -236
- package/dist/gobj-js.cjs.js.map +1 -1
- package/dist/gobj-js.cjs.min.js +2441 -1783
- package/dist/gobj-js.cjs.min.js.map +1 -1
- package/dist/gobj-js.es.js +1136 -237
- package/dist/gobj-js.es.js.map +1 -1
- package/dist/gobj-js.es.min.js +2313 -1653
- package/dist/gobj-js.es.min.js.map +1 -1
- package/dist/gobj-js.iife.js +1137 -236
- package/dist/gobj-js.iife.js.map +1 -1
- package/dist/gobj-js.iife.min.js +2365 -1707
- package/dist/gobj-js.iife.min.js.map +1 -1
- package/dist/gobj-js.umd.js +1137 -236
- package/dist/gobj-js.umd.js.map +1 -1
- package/dist/gobj-js.umd.min.js +2365 -1707
- package/dist/gobj-js.umd.min.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -282,7 +282,9 @@ const attrs_table = [
|
|
|
282
282
|
|
|
283
283
|
**Data types (`data_type_t`):** `DTP_STRING`, `DTP_BOOLEAN`, `DTP_INTEGER`, `DTP_REAL`, `DTP_LIST`, `DTP_DICT`, `DTP_JSON`, `DTP_POINTER`
|
|
284
284
|
|
|
285
|
-
**Flags (`sdata_flag_t`):** `SDF_RD`, `SDF_WR`, `SDF_PERSIST`, `SDF_STATS`, `SDF_AUTHZ_R`, `SDF_AUTHZ_W`, `SDF_REQUIRED`, `SDF_VOLATIL`
|
|
285
|
+
**Flags (`sdata_flag_t`):** `SDF_RD`, `SDF_WR`, `SDF_PERSIST`, `SDF_STATS`, `SDF_AUTHZ_R`, `SDF_AUTHZ_W`, `SDF_REQUIRED`, `SDF_VOLATIL`, `SDF_SECRET`
|
|
286
|
+
|
|
287
|
+
**A value is read as the attribute's type, as in C** (`gobj_write_attr()`, the kw of `gobj_create()`, `gobj_write_attrs()`, the persistent attrs; 7.26.22+): a string for a boolean, integer, real, list or dict is read from its text by the C command parser's grammar (`command_parameter_from_json()`: `"yes"` is `true`, `"42"` is 42, `"007"` and `"12abc"` are refused), a number or a boolean as the exact type (`2.7` to an integer is refused). A refused value is not written: one `log_error` names the attr, its type, why and the value (masked, capped; a `SDF_SECRET` one never shown). A key of a kw whose value is `undefined` is an absent key; `gobj_write_attr()` of `undefined` to a typed attr is refused. The typed writers read the value as THEIR type by the same grammar (`gobj_write_integer_attr(g, "x", 2.5)` is refused, `gobj_write_bool_attr(g, "on", "yes")` is `true`), and `gobj_write_str_attr()` writes `null`/`undefined` as `""`, never the text `"null"`.
|
|
286
288
|
|
|
287
289
|
### Events & Pub-Sub
|
|
288
290
|
|
|
@@ -415,6 +417,45 @@ gobj_is_volatil(gobj) // → boolean
|
|
|
415
417
|
gobj_is_pure_child(gobj) // → boolean
|
|
416
418
|
```
|
|
417
419
|
|
|
420
|
+
**A gobj is not destroyed under code that still runs on it** (7.26.22+, as the
|
|
421
|
+
C kernel since 7.26.10). `gobj_publish_event()` and `gobj_send_event()` run
|
|
422
|
+
synchronously, and the code of the publisher (or of the outer action) goes on
|
|
423
|
+
when they return. So `gobj_destroy()` logs an ERROR with the stack when it
|
|
424
|
+
destroys the publisher of a publication in progress, or one of its ancestors —
|
|
425
|
+
*"Destroying a gobj while its tree is publishing"* — or a gobj whose outer
|
|
426
|
+
action is still running — *"Destroying a gobj while one of its actions is
|
|
427
|
+
still running"*. The line names `destroying`, `publisher`/`running`, `event`,
|
|
428
|
+
`destroyer` and `inner_event`. The destroy is done all the same. A gobj that
|
|
429
|
+
destroys itself in its own action, and a host that destroys its transport in
|
|
430
|
+
the transport's `EV_STOPPED`, are not errors.
|
|
431
|
+
|
|
432
|
+
The fix is to leave the stack: post an event to yourself, and destroy in its
|
|
433
|
+
action. The event is an INPUT event of your gclass (FSM and `event_types`):
|
|
434
|
+
|
|
435
|
+
```javascript
|
|
436
|
+
// Wrong: EV_TIMEOUT comes from the C_TIMER child, inside its publication.
|
|
437
|
+
function ac_timeout(gobj, event, kw, src) {
|
|
438
|
+
gobj_stop(src);
|
|
439
|
+
gobj_destroy(src);
|
|
440
|
+
return 0;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Right: the destroy runs on the next turn, from a clean stack.
|
|
444
|
+
function ac_timeout(gobj, event, kw, src) {
|
|
445
|
+
gobj_post_event(gobj, "EV_TIMER_DONE", {timer: gobj_name(src)}, gobj);
|
|
446
|
+
return 0;
|
|
447
|
+
}
|
|
448
|
+
function ac_timer_done(gobj, event, kw, src) {
|
|
449
|
+
let timer = gobj.priv.timer; // resolve the identity the kw carries
|
|
450
|
+
if(timer && gobj_name(timer) === kw.timer) {
|
|
451
|
+
gobj_stop(timer);
|
|
452
|
+
gobj_destroy(timer);
|
|
453
|
+
gobj.priv.timer = null;
|
|
454
|
+
}
|
|
455
|
+
return 0;
|
|
456
|
+
}
|
|
457
|
+
```
|
|
458
|
+
|
|
418
459
|
### State Machine
|
|
419
460
|
|
|
420
461
|
```javascript
|
|
@@ -674,16 +715,36 @@ is_secret_name("mapping") // → false (pin inside a word)
|
|
|
674
715
|
is_secret_name("token_endpoint") // → false (names something ABOUT one)
|
|
675
716
|
mask_secrets_inline("login user=a passw=x") // → "login user=a passw=********"
|
|
676
717
|
mask_secrets_inline("curl -H 'Authorization: Bearer abc' u")
|
|
677
|
-
// → "curl -H 'Authorization:
|
|
718
|
+
// → "curl -H 'Authorization: ********' u"
|
|
719
|
+
mask_secrets_inline("sent Bearer mF_9.B5f-4.1JqM") // → "sent Bearer ********"
|
|
720
|
+
mask_secrets_inline("the bearer of this letter") // → null: prose
|
|
721
|
+
mask_secrets_inline("\"password\": hunter2") // → "\"password\": ********"
|
|
722
|
+
mask_secrets_inline("GET https://h/get?token=abc&x=1") // → "GET https://h/get?token=********&x=1"
|
|
678
723
|
json_mask_secrets({user: "a", password: "x"}) // → {user: "a", password: "********"}
|
|
679
724
|
json_mask_secrets({note: "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ4In0.c2ln"})
|
|
680
725
|
// → {note: "********"}: a JWT under any key
|
|
681
726
|
trace_json_masked(kw, "sent") // trace_json() of the masked copy
|
|
682
727
|
```
|
|
683
728
|
|
|
684
|
-
As the C kernel's: the same names, the same
|
|
685
|
-
|
|
686
|
-
|
|
729
|
+
As the C kernel's: the same names, the same rules. By name: the value of a
|
|
730
|
+
`name=value` and of a `name: value` (`"password": x`, `Authorization: Basic x`,
|
|
731
|
+
`bearer: tok`, `{\"password\":\"x\"}` of a json inside a json) whose name is
|
|
732
|
+
a secret's, whole. By value: a JWT or a JWE (`eyJ`, base64url and a `.`: also
|
|
733
|
+
one a cap cut), and after `Bearer` or `Basic` the word that can be a credential
|
|
734
|
+
-- quoted, after the scheme doubled, or not a word of prose (a digit, a symbol,
|
|
735
|
+
a character that is no ASCII, its case mixed, 24 characters or more; for
|
|
736
|
+
`Bearer` 8 at least, for `Basic` a run of base64 that decodes to a
|
|
737
|
+
`user:password`). The name of a `name=value` is also the run of name
|
|
738
|
+
characters before the `=`, as in a query string (`https://h/get?token=x`). A
|
|
739
|
+
name is judged by its last 128 bytes of UTF-8 and its case folded in ASCII, as
|
|
740
|
+
C judges it. Each rule judges the text as it came, and a run of characters to
|
|
741
|
+
mask is one `********`: nothing that 7.26.19 or 7.26.20 masked is shown, but
|
|
742
|
+
the word after a bare `Bearer` that cannot be a credential, and a name that C
|
|
743
|
+
judges otherwise (over 128 bytes, or with a letter that is no ASCII). A key
|
|
744
|
+
is judged as a name, never as a value: a key that is itself a credential (a
|
|
745
|
+
dict keyed by tokens, `{"eyJ...": 1}`) is shown as it is. A NUL in a string is
|
|
746
|
+
read as a blank; linear and bounded (a text over 4 MB is not shown at all).
|
|
747
|
+
`key` and `cert` are not secrets' names.
|
|
687
748
|
|
|
688
749
|
### Logging
|
|
689
750
|
|
|
@@ -895,7 +956,11 @@ set_timeout_periodic(timer_gobj, 1000);
|
|
|
895
956
|
clear_timeout(timer_gobj);
|
|
896
957
|
```
|
|
897
958
|
|
|
898
|
-
Events published: `EV_TIMEOUT`, `EV_TIMEOUT_PERIODIC
|
|
959
|
+
Events published: `EV_TIMEOUT`, `EV_TIMEOUT_PERIODIC`. They go to the
|
|
960
|
+
`subscriber` attr, else, for a pure child, to its parent, which the timer
|
|
961
|
+
subscribes in `mt_create` — the C timer's rule. Up to 7.26.21 a pure child
|
|
962
|
+
SENT the timeout to its parent instead of publishing it (and to its parent
|
|
963
|
+
even when it had a `subscriber`).
|
|
899
964
|
|
|
900
965
|
Attributes: `subscriber`, `periodic`, `msec`
|
|
901
966
|
|
|
@@ -917,6 +982,8 @@ let remote = gobj_create_service("backend", "C_IEVENT_CLI", {
|
|
|
917
982
|
|
|
918
983
|
Key attributes: `url`, `jwt`, `wanted_yuno_role`, `wanted_yuno_name`, `wanted_yuno_service`, `remote_yuno_role`, `remote_yuno_name`, `remote_yuno_service`, `required_services`, `timeout_retry`, `timeout_retry_max`
|
|
919
984
|
|
|
985
|
+
Its events (`EV_ON_OPEN`, `EV_ON_CLOSE`, `EV_ON_OPEN_ERROR`, `EV_ON_ID_NAK` and every message that names no service) are PUBLISHED: to the `subscriber` attr, else, for a pure child, to its parent, which it subscribes in `mt_create` — one subscription, as the C transport. Up to 7.26.21 a pure child SENT three of them to its parent and subscribed nobody, so its parent never heard `EV_ON_CLOSE` / `EV_ON_OPEN_ERROR`.
|
|
986
|
+
|
|
920
987
|
**`required_services`** (default `[]`) is the list this link advertises in its
|
|
921
988
|
identity_card, which the remote's `C_AUTHZ` uses to authorize commands. It is
|
|
922
989
|
**per link**: empty falls back to the yuno's own `required_services`, so a
|