@yuneta/gobj-ui 7.25.17 → 7.25.18

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 CHANGED
@@ -989,6 +989,35 @@ hold the list again; the cell and a delete's question count either shape. The
989
989
  search box no longer finds a parent row by the id of one of its children: to
990
990
  find what hangs from a row, click its hook.
991
991
 
992
+ ### What a write says to the host: `EV_RECORD_WRITTEN`
993
+
994
+ `C_YUI_TREEDB_TOPICS` and `C_YUI_TREEDB_GRAPH` publish `EV_RECORD_WRITTEN`
995
+ when a write of THEIRS is answered with success: a host whose work is not
996
+ finished with the record (a schema editor, a pending Apply) needs that, and the
997
+ `EV_TREEDB_NODE_*` events cannot tell its own writes from anybody else's. The
998
+ graph does not report `__graphs__`, its own bookkeeping.
999
+
1000
+ ```js
1001
+ // kw of EV_RECORD_WRITTEN
1002
+ {
1003
+ treedb_name: "treedb_test", // the view's own treedb
1004
+ topic_name: "yunos", // the topic written (the CHILD's, for a link)
1005
+ record: {id: "1", x: 1, y: 2}, // the node the store answered, as written
1006
+ created: false, // true for create-node
1007
+ command: "update-node", // create/update/delete-node, link/unlink-nodes
1008
+ parent_ref: "realms^r1^yunos", // graph, link/unlink only
1009
+ child_ref: "yunos^1" // graph, link/unlink only
1010
+ }
1011
+ ```
1012
+
1013
+ Since `7.25.18` every field carries what it says. They were read from the
1014
+ answer's command frame, which carries back only the request's
1015
+ `__md_command__` -- `C_IEVENT_CLI` and gui_agent's `C_AGENT_TREEDB_LINK` both
1016
+ do -- so `treedb_name` and `record` arrived empty, and a link named no topic.
1017
+ `treedb_name` is now the view's, `record` is the node the answer carries (a
1018
+ delete answers the node deleted, a link the child), and a link echoes its topic
1019
+ and refs in `__md_command__`.
1020
+
992
1021
  ### Read-only treedbs: `readonly`
993
1022
 
994
1023
  `C_YUI_TREEDB_TOPICS` and `C_YUI_TREEDB_GRAPH` take a **`readonly`** attr; the
@@ -24924,6 +24924,17 @@ function treedb_nodes$1(gobj, treedb_name, topic_name, options, page, purpose) {
24924
24924
  return 0;
24925
24925
  }
24926
24926
  /************************************************************
24927
+ * The record a write answered: the node the store wrote (an
24928
+ * update or a create), deleted, or the child of a link. The
24929
+ * answer's frame carries back only `__md_command__`, never the
24930
+ * request's own record.
24931
+ ************************************************************/
24932
+ function answered_record$1(data) {
24933
+ if (data && typeof data === "object" && !Array.isArray(data)) return data;
24934
+ if (Array.isArray(data) && data[0] && typeof data[0] === "object") return data[0];
24935
+ return {};
24936
+ }
24937
+ /************************************************************
24927
24938
  * Command to remote service
24928
24939
  ************************************************************/
24929
24940
  function treedb_update_node$1(gobj, treedb_name, topic_name, record, options, form_write) {
@@ -25245,9 +25256,9 @@ function ac_mt_command_answer$2(gobj, event, kw, src) {
25245
25256
  case "create-node":
25246
25257
  case "update-node":
25247
25258
  (0, _yuneta_gobj_js.gobj_publish_event)(gobj, "EV_RECORD_WRITTEN", {
25248
- treedb_name: (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "treedb_name", "", 0),
25259
+ treedb_name: (0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "treedb_name"),
25249
25260
  topic_name: (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "topic_name", "", 0),
25250
- record: (0, _yuneta_gobj_js.kw_get_dict)(gobj, kw_command, "record", {}, 0),
25261
+ record: answered_record$1(data),
25251
25262
  created: command === "create-node",
25252
25263
  command
25253
25264
  });
@@ -68408,6 +68419,29 @@ function treedb_delete_node(gobj, treedb_name, topic_name, record, options) {
68408
68419
  if (ret) (0, _yuneta_gobj_js.log_error)(ret);
68409
68420
  }
68410
68421
  /************************************************************
68422
+ * What a link or an unlink asks back with its answer: the
68423
+ * topic of the CHILD (the node a link saves) and both refs.
68424
+ * `child_ref` is "topic^id", `parent_ref` "topic^id^hook".
68425
+ ************************************************************/
68426
+ function link_echo(parent_ref, child_ref) {
68427
+ return {
68428
+ topic_name: typeof child_ref === "string" ? child_ref.split("^")[0] : "",
68429
+ parent_ref,
68430
+ child_ref
68431
+ };
68432
+ }
68433
+ /************************************************************
68434
+ * The record a write answered: the node the store wrote (an
68435
+ * update or a create), deleted, or the child of a link. The
68436
+ * answer's frame carries back only `__md_command__`, never the
68437
+ * request's own record.
68438
+ ************************************************************/
68439
+ function answered_record(data) {
68440
+ if (data && typeof data === "object" && !Array.isArray(data)) return data;
68441
+ if (Array.isArray(data) && data[0] && typeof data[0] === "object") return data[0];
68442
+ return {};
68443
+ }
68444
+ /************************************************************
68411
68445
  * Command to remote service
68412
68446
  ************************************************************/
68413
68447
  function treedb_link_nodes(gobj, treedb_name, parent_ref, child_ref, options) {
@@ -68424,6 +68458,7 @@ function treedb_link_nodes(gobj, treedb_name, parent_ref, child_ref, options) {
68424
68458
  child_ref,
68425
68459
  options: options || {}
68426
68460
  };
68461
+ kw.__md_command__ = link_echo(parent_ref, child_ref);
68427
68462
  let ret = (0, _yuneta_gobj_js.gobj_command)(priv.gobj_remote_yuno, command, kw, gobj);
68428
68463
  if (ret) (0, _yuneta_gobj_js.log_error)(ret);
68429
68464
  }
@@ -68444,6 +68479,7 @@ function treedb_unlink_nodes(gobj, treedb_name, parent_ref, child_ref, options)
68444
68479
  child_ref,
68445
68480
  options: options || {}
68446
68481
  };
68482
+ kw.__md_command__ = link_echo(parent_ref, child_ref);
68447
68483
  let ret = (0, _yuneta_gobj_js.gobj_command)(priv.gobj_remote_yuno, command, kw, gobj);
68448
68484
  if (ret) (0, _yuneta_gobj_js.log_error)(ret);
68449
68485
  }
@@ -68658,13 +68694,20 @@ function ac_mt_command_answer$1(gobj, event, kw, src) {
68658
68694
  case "link-nodes":
68659
68695
  case "unlink-nodes":
68660
68696
  if (result < 0 && command === "update-node") graphs_write_refused(gobj, (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "topic_name", "", 0), (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "graph_topic", "", 0));
68661
- if (result >= 0 && (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "topic_name", "", 0) !== "__graphs__") (0, _yuneta_gobj_js.gobj_publish_event)(gobj, "EV_RECORD_WRITTEN", {
68662
- treedb_name: (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "treedb_name", "", 0),
68663
- topic_name: (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "topic_name", "", 0),
68664
- record: (0, _yuneta_gobj_js.kw_get_dict)(gobj, kw_command, "record", {}, 0),
68665
- created: command === "create-node",
68666
- command
68667
- });
68697
+ if (result >= 0 && (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "topic_name", "", 0) !== "__graphs__") {
68698
+ let written = {
68699
+ treedb_name: priv.treedb_name,
68700
+ topic_name: (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "topic_name", "", 0),
68701
+ record: answered_record(data),
68702
+ created: command === "create-node",
68703
+ command
68704
+ };
68705
+ if (command === "link-nodes" || command === "unlink-nodes") {
68706
+ written.parent_ref = (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "parent_ref", "", 0);
68707
+ written.child_ref = (0, _yuneta_gobj_js.kw_get_str)(gobj, kw_command, "child_ref", "", 0);
68708
+ }
68709
+ (0, _yuneta_gobj_js.gobj_publish_event)(gobj, "EV_RECORD_WRITTEN", written);
68710
+ }
68668
68711
  break;
68669
68712
  default: (0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)} Command unknown: ${command}`);
68670
68713
  }
@@ -24919,6 +24919,17 @@ function treedb_nodes$1(gobj, treedb_name, topic_name, options, page, purpose) {
24919
24919
  return 0;
24920
24920
  }
24921
24921
  /************************************************************
24922
+ * The record a write answered: the node the store wrote (an
24923
+ * update or a create), deleted, or the child of a link. The
24924
+ * answer's frame carries back only `__md_command__`, never the
24925
+ * request's own record.
24926
+ ************************************************************/
24927
+ function answered_record$1(data) {
24928
+ if (data && typeof data === "object" && !Array.isArray(data)) return data;
24929
+ if (Array.isArray(data) && data[0] && typeof data[0] === "object") return data[0];
24930
+ return {};
24931
+ }
24932
+ /************************************************************
24922
24933
  * Command to remote service
24923
24934
  ************************************************************/
24924
24935
  function treedb_update_node$1(gobj, treedb_name, topic_name, record, options, form_write) {
@@ -25240,9 +25251,9 @@ function ac_mt_command_answer$2(gobj, event, kw, src) {
25240
25251
  case "create-node":
25241
25252
  case "update-node":
25242
25253
  gobj_publish_event(gobj, "EV_RECORD_WRITTEN", {
25243
- treedb_name: kw_get_str(gobj, kw_command, "treedb_name", "", 0),
25254
+ treedb_name: gobj_read_str_attr(gobj, "treedb_name"),
25244
25255
  topic_name: kw_get_str(gobj, kw_command, "topic_name", "", 0),
25245
- record: kw_get_dict(gobj, kw_command, "record", {}, 0),
25256
+ record: answered_record$1(data),
25246
25257
  created: command === "create-node",
25247
25258
  command
25248
25259
  });
@@ -68403,6 +68414,29 @@ function treedb_delete_node(gobj, treedb_name, topic_name, record, options) {
68403
68414
  if (ret) log_error(ret);
68404
68415
  }
68405
68416
  /************************************************************
68417
+ * What a link or an unlink asks back with its answer: the
68418
+ * topic of the CHILD (the node a link saves) and both refs.
68419
+ * `child_ref` is "topic^id", `parent_ref` "topic^id^hook".
68420
+ ************************************************************/
68421
+ function link_echo(parent_ref, child_ref) {
68422
+ return {
68423
+ topic_name: typeof child_ref === "string" ? child_ref.split("^")[0] : "",
68424
+ parent_ref,
68425
+ child_ref
68426
+ };
68427
+ }
68428
+ /************************************************************
68429
+ * The record a write answered: the node the store wrote (an
68430
+ * update or a create), deleted, or the child of a link. The
68431
+ * answer's frame carries back only `__md_command__`, never the
68432
+ * request's own record.
68433
+ ************************************************************/
68434
+ function answered_record(data) {
68435
+ if (data && typeof data === "object" && !Array.isArray(data)) return data;
68436
+ if (Array.isArray(data) && data[0] && typeof data[0] === "object") return data[0];
68437
+ return {};
68438
+ }
68439
+ /************************************************************
68406
68440
  * Command to remote service
68407
68441
  ************************************************************/
68408
68442
  function treedb_link_nodes(gobj, treedb_name, parent_ref, child_ref, options) {
@@ -68419,6 +68453,7 @@ function treedb_link_nodes(gobj, treedb_name, parent_ref, child_ref, options) {
68419
68453
  child_ref,
68420
68454
  options: options || {}
68421
68455
  };
68456
+ kw.__md_command__ = link_echo(parent_ref, child_ref);
68422
68457
  let ret = gobj_command(priv.gobj_remote_yuno, command, kw, gobj);
68423
68458
  if (ret) log_error(ret);
68424
68459
  }
@@ -68439,6 +68474,7 @@ function treedb_unlink_nodes(gobj, treedb_name, parent_ref, child_ref, options)
68439
68474
  child_ref,
68440
68475
  options: options || {}
68441
68476
  };
68477
+ kw.__md_command__ = link_echo(parent_ref, child_ref);
68442
68478
  let ret = gobj_command(priv.gobj_remote_yuno, command, kw, gobj);
68443
68479
  if (ret) log_error(ret);
68444
68480
  }
@@ -68653,13 +68689,20 @@ function ac_mt_command_answer$1(gobj, event, kw, src) {
68653
68689
  case "link-nodes":
68654
68690
  case "unlink-nodes":
68655
68691
  if (result < 0 && command === "update-node") graphs_write_refused(gobj, kw_get_str(gobj, kw_command, "topic_name", "", 0), kw_get_str(gobj, kw_command, "graph_topic", "", 0));
68656
- if (result >= 0 && kw_get_str(gobj, kw_command, "topic_name", "", 0) !== "__graphs__") gobj_publish_event(gobj, "EV_RECORD_WRITTEN", {
68657
- treedb_name: kw_get_str(gobj, kw_command, "treedb_name", "", 0),
68658
- topic_name: kw_get_str(gobj, kw_command, "topic_name", "", 0),
68659
- record: kw_get_dict(gobj, kw_command, "record", {}, 0),
68660
- created: command === "create-node",
68661
- command
68662
- });
68692
+ if (result >= 0 && kw_get_str(gobj, kw_command, "topic_name", "", 0) !== "__graphs__") {
68693
+ let written = {
68694
+ treedb_name: priv.treedb_name,
68695
+ topic_name: kw_get_str(gobj, kw_command, "topic_name", "", 0),
68696
+ record: answered_record(data),
68697
+ created: command === "create-node",
68698
+ command
68699
+ };
68700
+ if (command === "link-nodes" || command === "unlink-nodes") {
68701
+ written.parent_ref = kw_get_str(gobj, kw_command, "parent_ref", "", 0);
68702
+ written.child_ref = kw_get_str(gobj, kw_command, "child_ref", "", 0);
68703
+ }
68704
+ gobj_publish_event(gobj, "EV_RECORD_WRITTEN", written);
68705
+ }
68663
68706
  break;
68664
68707
  default: log_error(`${gobj_short_name(gobj)} Command unknown: ${command}`);
68665
68708
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuneta/gobj-ui",
3
- "version": "7.25.17",
3
+ "version": "7.25.18",
4
4
  "type": "module",
5
5
  "main": "dist/gobj-ui.cjs.js",
6
6
  "module": "dist/gobj-ui.es.js",
@@ -1575,6 +1575,38 @@ function treedb_delete_node(gobj, treedb_name, topic_name, record, options)
1575
1575
  }
1576
1576
  }
1577
1577
 
1578
+ /************************************************************
1579
+ * What a link or an unlink asks back with its answer: the
1580
+ * topic of the CHILD (the node a link saves) and both refs.
1581
+ * `child_ref` is "topic^id", `parent_ref` "topic^id^hook".
1582
+ ************************************************************/
1583
+ function link_echo(parent_ref, child_ref)
1584
+ {
1585
+ let child_topic = (typeof child_ref === "string") ? child_ref.split("^")[0] : "";
1586
+ return {
1587
+ topic_name: child_topic,
1588
+ parent_ref: parent_ref,
1589
+ child_ref: child_ref
1590
+ };
1591
+ }
1592
+
1593
+ /************************************************************
1594
+ * The record a write answered: the node the store wrote (an
1595
+ * update or a create), deleted, or the child of a link. The
1596
+ * answer's frame carries back only `__md_command__`, never the
1597
+ * request's own record.
1598
+ ************************************************************/
1599
+ function answered_record(data)
1600
+ {
1601
+ if(data && typeof data === "object" && !Array.isArray(data)) {
1602
+ return data;
1603
+ }
1604
+ if(Array.isArray(data) && data[0] && typeof data[0] === "object") {
1605
+ return data[0];
1606
+ }
1607
+ return {};
1608
+ }
1609
+
1578
1610
  /************************************************************
1579
1611
  * Command to remote service
1580
1612
  ************************************************************/
@@ -1596,6 +1628,7 @@ function treedb_link_nodes(gobj, treedb_name, parent_ref, child_ref, options)
1596
1628
  child_ref: child_ref,
1597
1629
  options: options || {}
1598
1630
  };
1631
+ kw.__md_command__ = link_echo(parent_ref, child_ref);
1599
1632
 
1600
1633
  let ret = gobj_command(priv.gobj_remote_yuno,
1601
1634
  command,
@@ -1628,6 +1661,7 @@ function treedb_unlink_nodes(gobj, treedb_name, parent_ref, child_ref, options)
1628
1661
  child_ref: child_ref,
1629
1662
  options: options || {}
1630
1663
  };
1664
+ kw.__md_command__ = link_echo(parent_ref, child_ref);
1631
1665
 
1632
1666
  let ret = gobj_command(priv.gobj_remote_yuno,
1633
1667
  command,
@@ -2111,8 +2145,12 @@ function ac_mt_command_answer(gobj, event, kw, src)
2111
2145
  * answering its own writes in a loop.
2112
2146
  *
2113
2147
  * Same event and same kw as C_YUI_TREEDB_TOPICS, plus `command`:
2114
- * in a graph a LINK is as much a write as a record is, and the
2115
- * three of them carry different halves of the kw.
2148
+ * in a graph a LINK is as much a write as a record is, and a
2149
+ * link adds its two refs. Read from what THIS view knows and
2150
+ * from the answer, never from the request: the frame carries
2151
+ * back only `__md_command__`. `treedb_name` is the view's,
2152
+ * `record` is the node the store answered (the child, for a
2153
+ * link).
2116
2154
  *
2117
2155
  * `__graphs__` is EXCLUDED, and that exclusion is the point of
2118
2156
  * reading this comment: the view writes that topic ITSELF, one
@@ -2128,13 +2166,18 @@ function ac_mt_command_answer(gobj, event, kw, src)
2128
2166
  }
2129
2167
  if(result >= 0 &&
2130
2168
  kw_get_str(gobj, kw_command, "topic_name", "", 0) !== "__graphs__") {
2131
- gobj_publish_event(gobj, "EV_RECORD_WRITTEN", {
2132
- treedb_name: kw_get_str(gobj, kw_command, "treedb_name", "", 0),
2169
+ let written = {
2170
+ treedb_name: priv.treedb_name,
2133
2171
  topic_name: kw_get_str(gobj, kw_command, "topic_name", "", 0),
2134
- record: kw_get_dict(gobj, kw_command, "record", {}, 0),
2172
+ record: answered_record(data),
2135
2173
  created: (command === "create-node"),
2136
2174
  command: command
2137
- });
2175
+ };
2176
+ if(command === "link-nodes" || command === "unlink-nodes") {
2177
+ written.parent_ref = kw_get_str(gobj, kw_command, "parent_ref", "", 0);
2178
+ written.child_ref = kw_get_str(gobj, kw_command, "child_ref", "", 0);
2179
+ }
2180
+ gobj_publish_event(gobj, "EV_RECORD_WRITTEN", written);
2138
2181
  }
2139
2182
  break;
2140
2183
 
@@ -1624,6 +1624,23 @@ function treedb_nodes(gobj, treedb_name, topic_name, options, page, purpose)
1624
1624
  return 0;
1625
1625
  }
1626
1626
 
1627
+ /************************************************************
1628
+ * The record a write answered: the node the store wrote (an
1629
+ * update or a create), deleted, or the child of a link. The
1630
+ * answer's frame carries back only `__md_command__`, never the
1631
+ * request's own record.
1632
+ ************************************************************/
1633
+ function answered_record(data)
1634
+ {
1635
+ if(data && typeof data === "object" && !Array.isArray(data)) {
1636
+ return data;
1637
+ }
1638
+ if(Array.isArray(data) && data[0] && typeof data[0] === "object") {
1639
+ return data[0];
1640
+ }
1641
+ return {};
1642
+ }
1643
+
1627
1644
  /************************************************************
1628
1645
  * Command to remote service
1629
1646
  ************************************************************/
@@ -2210,10 +2227,14 @@ function ac_mt_command_answer(gobj, event, kw, src)
2210
2227
  * and cannot use the node events without answering its own writes
2211
2228
  * in a loop.
2212
2229
  */
2230
+ /* From what THIS view knows and from the answer, never from
2231
+ * the request: the frame carries back only `__md_command__`,
2232
+ * so `treedb_name` and `record` read there arrived empty.
2233
+ * `record` is the node the store answered, as it was written. */
2213
2234
  gobj_publish_event(gobj, "EV_RECORD_WRITTEN", {
2214
- treedb_name: kw_get_str(gobj, kw_command, "treedb_name", "", 0),
2235
+ treedb_name: gobj_read_str_attr(gobj, "treedb_name"),
2215
2236
  topic_name: kw_get_str(gobj, kw_command, "topic_name", "", 0),
2216
- record: kw_get_dict(gobj, kw_command, "record", {}, 0),
2237
+ record: answered_record(data),
2217
2238
  created: (command === "create-node"),
2218
2239
  command: command
2219
2240
  });
@@ -43,6 +43,7 @@ const {
43
43
  } = await import("@yuneta/gobj-js");
44
44
 
45
45
  const logged = [];
46
+ const written = []; /* the EV_RECORD_WRITTEN the host heard */
46
47
  const commands = []; /* what the fake transport was asked */
47
48
  const told = []; /* what the fake engine was told */
48
49
  let refuse_on_the_way = false;
@@ -65,6 +66,20 @@ beforeAll(async () => {
65
66
  });
66
67
 
67
68
  gclass_create("C_TEST_HOST", [], [["ST_IDLE", []]], {}, 0, [SDATA_END()], {}, 0, 0, 0, 0);
69
+ /* The host of the view: it hears what the view publishes. */
70
+ gclass_create(
71
+ "C_TEST_GRAPH_HOST",
72
+ [["EV_RECORD_WRITTEN", 0], ["EV_TOPIC_SELECTED", 0], ["EV_OPERATION_MODE_CHANGED", 0]],
73
+ [["ST_IDLE", [
74
+ ["EV_RECORD_WRITTEN", (gobj, event, kw) => {
75
+ written.push(kw);
76
+ return 0;
77
+ }, null],
78
+ ["EV_TOPIC_SELECTED", () => 0, null],
79
+ ["EV_OPERATION_MODE_CHANGED", () => 0, null]
80
+ ]]],
81
+ {}, 0, [SDATA_END()], {}, 0, 0, 0, 0
82
+ );
68
83
  gclass_create(
69
84
  "C_TEST_REMOTE",
70
85
  [],
@@ -120,6 +135,7 @@ beforeAll(async () => {
120
135
 
121
136
  beforeEach(() => {
122
137
  logged.length = 0;
138
+ written.length = 0;
123
139
  commands.length = 0;
124
140
  told.length = 0;
125
141
  refuse_on_the_way = false;
@@ -129,9 +145,11 @@ function build(name)
129
145
  {
130
146
  const remote = gobj_create_service(`${name}_remote`, "C_TEST_REMOTE", {}, yuno);
131
147
  gobj_change_state(remote, "ST_SESSION");
148
+ const view_host = gobj_create(`${name}_view_host`, "C_TEST_GRAPH_HOST", {}, yuno);
132
149
  const host = gobj_create_service(`${name}_graph`, "C_YUI_TREEDB_GRAPH", {
133
150
  gobj_remote_yuno: remote,
134
- treedb_name: "treedb_test"
151
+ treedb_name: "treedb_test",
152
+ subscriber: view_host
135
153
  }, yuno);
136
154
  const engine = host.priv.gobj_nodes_tree;
137
155
  expect(engine).toBeTruthy();
@@ -154,13 +172,13 @@ function save_arrangement(engine, topic)
154
172
  * mt_command, gui_agent's C_AGENT_TREEDB_LINK), never the request's
155
173
  * own kw. Echoing the whole kw here once hid that the refusal read
156
174
  * its topic from a `record` no real answer carries. */
157
- function answer(host, remote, request, result, comment)
175
+ function answer(host, remote, request, result, comment, data)
158
176
  {
159
177
  const md_command = request.kw.__md_command__ || {};
160
178
  gobj_send_event(host, "EV_MT_COMMAND_ANSWER", {
161
179
  result: result,
162
180
  comment: comment || "",
163
- data: null,
181
+ data: (data === undefined) ? null : data,
164
182
  __md_iev__: {command_stack: [{command: request.command, kw: md_command}]}
165
183
  }, remote);
166
184
  }
@@ -213,3 +231,53 @@ describe("a __graphs__ write that does not land is said to the engine", () => {
213
231
  expect(refused()).toEqual([]);
214
232
  });
215
233
  });
234
+
235
+ /* What THIS view wrote, told to its host. The answer carries back only
236
+ * `__md_command__`: `treedb_name` and `record` read from that frame
237
+ * arrived empty with every real transport. */
238
+ describe("EV_RECORD_WRITTEN carries what it says", () => {
239
+
240
+ test("an update: the treedb, the topic and the record the store answered", () => {
241
+ const {remote, host, engine} = build("w1");
242
+ logged.length = 0; /* the fake engine's fixture, not the check */
243
+ gobj_send_event(host, "EV_UPDATE_NODE", {
244
+ topic_name: "yunos", record: {id: "1", x: 1}
245
+ }, engine);
246
+ const [write] = commands;
247
+ answer(host, remote, write, 0, "", {id: "1", x: 1, y: 2});
248
+ expect(written).toEqual([{
249
+ treedb_name: "treedb_test",
250
+ topic_name: "yunos",
251
+ record: {id: "1", x: 1, y: 2},
252
+ created: false,
253
+ command: "update-node"
254
+ }]);
255
+ expect(logged.filter((l) => l.level === "error")).toEqual([]);
256
+ });
257
+
258
+ test("a link: the child's topic, both refs, and the child the store answered", () => {
259
+ const {remote, host, engine} = build("w2");
260
+ gobj_send_event(host, "EV_LINK_NODES", {
261
+ parent_ref: "realms^r1^yunos", child_ref: "yunos^1"
262
+ }, engine);
263
+ const [link] = commands;
264
+ expect(link.command).toBe("link-nodes");
265
+ answer(host, remote, link, 0, "", {id: "1", realms: ["realms^r1^yunos"]});
266
+ expect(written).toEqual([{
267
+ treedb_name: "treedb_test",
268
+ topic_name: "yunos",
269
+ record: {id: "1", realms: ["realms^r1^yunos"]},
270
+ parent_ref: "realms^r1^yunos",
271
+ child_ref: "yunos^1",
272
+ created: false,
273
+ command: "link-nodes"
274
+ }]);
275
+ });
276
+
277
+ test("the arrangement (__graphs__) is not reported", () => {
278
+ const {remote, host, engine} = build("w3");
279
+ save_arrangement(engine, "yunos");
280
+ answer(host, remote, commands[0], 0, "", {id: "yunos"});
281
+ expect(written).toEqual([]);
282
+ });
283
+ });
@@ -29,6 +29,7 @@ const {register_c_yui_shell, yui_shell_set_connection_state} = await import("./c
29
29
  const {register_c_yui_treedb_topics} = await import("./c_yui_treedb_topics.js");
30
30
 
31
31
  const logged = [];
32
+ const written = []; /* the EV_RECORD_WRITTEN the host heard */
32
33
  const answers = []; /* what the fake forms were told */
33
34
  const loaded = []; /* the rows each fake form was loaded with */
34
35
  const commands = []; /* what the fake transport was asked */
@@ -103,7 +104,10 @@ beforeAll(() => {
103
104
  "C_TEST_VIEW_HOST",
104
105
  [["EV_RECORD_WRITTEN", 0], ["EV_TOPIC_SELECTED", 0]],
105
106
  [["ST_IDLE", [
106
- ["EV_RECORD_WRITTEN", () => 0, null],
107
+ ["EV_RECORD_WRITTEN", (gobj, event, kw) => {
108
+ written.push(kw);
109
+ return 0;
110
+ }, null],
107
111
  ["EV_TOPIC_SELECTED", () => 0, null]
108
112
  ]]],
109
113
  {}, 0, [SDATA_END()], {}, 0, 0, 0, 0
@@ -121,6 +125,7 @@ beforeAll(() => {
121
125
 
122
126
  beforeEach(() => {
123
127
  logged.length = 0;
128
+ written.length = 0;
124
129
  answers.length = 0;
125
130
  commands.length = 0;
126
131
  loaded.length = 0;
@@ -228,16 +233,26 @@ describe("a Save in flight when the backend drops", () => {
228
233
  save(topics, forms.roles, 1);
229
234
 
230
235
  /* The answer of the users write, the way C_IEVENT_CLI delivers it:
231
- * the request's frame on top of the command_stack. */
232
- const ok = {result: 0, comment: "", data: [{id: "x"}], __md_iev__: {
233
- command_stack: [{command: "update-node", kw: {
234
- topic_name: "users", treedb_name: "treedb_test", form_write: 1, record: {id: "x"}
235
- }}]
236
+ * the request's `__md_command__` as the frame on top of the
237
+ * command_stack, and nothing else of the request. */
238
+ const users_write = commands.find((c) => c.command === "update-node" &&
239
+ c.kw.topic_name === "users");
240
+ const ok = {result: 0, comment: "", data: [{id: "x", name: "stored"}], __md_iev__: {
241
+ command_stack: [{command: "update-node", kw: users_write.kw.__md_command__}]
236
242
  }};
237
243
  gobj_send_event(topics, "EV_MT_COMMAND_ANSWER", ok, remote);
238
244
  expect(answers).toEqual([
239
245
  {topic: "users", event: "EV_WRITE_DONE", form_write: 1},
240
246
  ]);
247
+ /* What the host is told names the treedb and carries the record
248
+ * the store answered: read off that frame, both arrived empty. */
249
+ expect(written).toEqual([{
250
+ treedb_name: "treedb_test",
251
+ topic_name: "users",
252
+ record: {id: "x", name: "stored"},
253
+ created: false,
254
+ command: "update-node"
255
+ }]);
241
256
 
242
257
  yui_shell_set_connection_state(shell, false);
243
258
  expect(answers).toEqual([
@@ -253,7 +268,7 @@ describe("a Save in flight when the backend drops", () => {
253
268
  */
254
269
  function failed_write(topic_name, form_write)
255
270
  {
256
- const md = {topic_name: topic_name, treedb_name: "treedb_test", record: {id: "x"}};
271
+ const md = {topic_name: topic_name}; /* the request's __md_command__, and only it */
257
272
  if(form_write) {
258
273
  md.form_write = form_write;
259
274
  }