kw, kwid and inter-event helpers¶
A kw is the JSON payload that travels with every event. These helpers read
it, write it, filter it and clone it.
Source code: src/helpers.js
Most helpers take gobj as their first parameter, and they use it only to name
the gobj in a log message. kw_has_key(), kw_pop() and kw_match_simple()
are the exceptions, and they take no gobj.
kw_flag_t¶
The flags of the typed readers. Combine them with the bit-or operator.
| Flag | Effect |
|---|---|
KW_REQUIRED | Writes a log error when the path does not exist, and in kw_get_dict() and kw_get_list() also when its value has a different type. kw_get_bool(), kw_get_int(), kw_get_real() and kw_get_str() log a value of a different type also without it, as in C. Example: kw_get_dict(gobj, {}, "cfg", null, kw_flag_t.KW_REQUIRED) gives null and logs “path not found: ‘cfg’”. |
KW_CREATE | Creates the path with the default value when it does not exist. |
KW_WILD_NUMBER | In kw_get_int(), kw_get_real() and kw_get_bool(): also reads a value of a simple type that is not the reader’s own (a boolean, a number, a string, null), and writes no log for it. A list or a dict gives 0 (false) and a log error. |
KW_EXTRACT | Deletes the key after the read, only when the reader answers with its value. |
KW_BACKWARD | Searches from the end in a list. |
KW_VERBOSE | Writes a log message when the operation fails. |
KW_LOWER | Puts the key in lower case. |
KW_RECURSIVE | Goes down into the sub-objects. |
Read and write¶
kw_has_key(kw, key)¶
Tells if kw has the key as its own property. It takes a key, not a path, and
it takes no gobj. Returns a boolean.
kw_find_path(gobj, kw, path, verbose)¶
Gives the value at a back-tick path. Returns undefined when the path does not
exist, as the C kw_find_path() returns NULL. With verbose set to true the
function writes a log error first.
When kw is not a dict or a list, or when a segment in the middle of the path
holds a scalar, the function logs “kw must be list or dict” and returns
undefined. A middle segment that is absent or null returns undefined, and
logs only when verbose is true. So a typed reader (kw_get_int(),
kw_get_str(), ...) that gets a bad kw returns its default (since gobj-js
7.25.6; before, a bad kw returned 0 and a null middle segment threw a
TypeError):
kw_find_path(null, {a: [{b: 1}, {b: 2}]}, "a`1`b", false); // 2
kw_find_path(null, {a: null}, "a`b", false); // undefined, no log
kw_get_int(null, null, "x", 5, 0); // 5, logged: kw must be list or dict: 'x'kw_delete(gobj, kw, path)¶
Deletes the key at a back-tick path. Returns 0.
kw_pop(kw1, kw2)¶
Deletes from kw1 every key that kw2 names. kw2 can be a string, an object
or an array, and an array goes down into each of its elements. It takes no
gobj, and it returns nothing.
kw_set_dict_value(gobj, kw, path, value)¶
Writes a value at a back-tick path, and creates the intermediate objects that
the path needs. It returns 0, or -1 with a logged error when kw is not an
object or when a middle segment is null or a scalar: nothing can be created
inside one, so the kw is left as it was (C logs and stops there too). A typed
reader with KW_CREATE over such a path answers its default.
const kw = {a: {}};
kw_set_dict_value(gobj, kw, "a`b`c", 1); // 0, kw is {a: {b: {c: 1}}}
kw_set_dict_value(gobj, {a: null}, "a`b", 1); // -1, logged
kw_get_int(gobj, {a: 5}, "a`b", 7, kw_flag_t.KW_CREATE); // 7, loggedkw_set_subdict_value(gobj, kw, path, key, value)¶
Writes key inside the object at path, and creates that object when it does
not exist.
Typed readers¶
Every reader takes the same five parameters, and each one gives the type of its
name. A value of a different type, or a key that is not there, gives the
default value back, as the C readers do: as you gave it in kw_get_str(),
kw_get_dict() and kw_get_list(), and converted to the reader’s type in
kw_get_bool() (Boolean()), kw_get_int() (parseInt()) and
kw_get_real() (Number()):
kw_get_str (gobj, {}, "name", null, 0); // null, as given
kw_get_dict(gobj, {}, "cfg", null, 0); // null, as given
kw_get_bool(gobj, {}, "on", 1, 0); // true: Boolean(1)
kw_get_int (gobj, {}, "port", "8080", 0); // 8080: parseInt("8080")
kw_get_real(gobj, {x: "1.5"}, "x", "2.5", 0); // 2.5, and logged: a string is not a numberWith KW_REQUIRED a missing key or a value of a different type writes a log
error; kw_get_bool(), kw_get_int(), kw_get_real() and kw_get_str() log
a value of a different type also without it, as in C (kw_get_str() does not
log a null value). In kw_get_bool(), kw_get_dict()
and kw_get_list(), KW_CREATE writes only a default of the right type. In
every typed reader, KW_EXTRACT deletes only a value that the reader gives
back: a value of a different type stays in the kw. Before gobj-js 7.25.2,
kw_get_list(), kw_get_dict() and kw_get_bool() did not keep this rule,
before 7.25.4 kw_get_int(), kw_get_real() and kw_get_str() did not, and
before 7.25.5 kw_get_str() logged a value of a different type only with
KW_REQUIRED (see each one below).
kw_get_bool (gobj, kw, path, default_value, flag)
kw_get_int (gobj, kw, path, default_value, flag)
kw_get_real (gobj, kw, path, default_value, flag)
kw_get_str (gobj, kw, path, default_value, flag)
kw_get_dict (gobj, kw, path, default_value, flag)
kw_get_list (gobj, kw, path, default_value, flag)
kw_get_dict_value(gobj, kw, path, default_value, flag)
kw_get_pointer (gobj, kw, path, default_value, flag)kw_get_bool()¶
Reads a boolean. Only a boolean is read: any other value gives the default
back, as a boolean, and writes a log error (“path MUST BE a json boolean”)
with or without KW_REQUIRED, as in C. With KW_WILD_NUMBER the function also
reads a number (0 is false), a string ("true" or "false" in any case,
else its decimal integer, as C’s atoi() reads it: "0x1F" is 0, so false)
and null (false), as in C; a list or a dict then gives false and a log
error (“path MUST BE a simple json element”). Before gobj-js 7.25.2 the value
went through Boolean(), so the string "false" was true. Before 7.25.3 a
value of another type gave the default back with no log. Before 7.25.5 the
string went through parseInt() with no base, which reads hex: "0x1F" was
true.
kw_get_bool(gobj, {on: true}, "on", false, 0); // true
kw_get_bool(gobj, {}, "on", true, 0); // true (the default)
kw_get_bool(gobj, {on: "false"}, "on", true, 0); // true, and logged: a string is not a boolean
kw_get_bool(gobj, {on: "false"}, "on", true, kw_flag_t.KW_WILD_NUMBER); // false
kw_get_bool(gobj, {on: 0}, "on", true, kw_flag_t.KW_WILD_NUMBER); // false
kw_get_bool(gobj, {on: "12"}, "on", false, kw_flag_t.KW_WILD_NUMBER); // true
kw_get_bool(gobj, {on: "0x1F"}, "on", true, kw_flag_t.KW_WILD_NUMBER); // false: atoi("0x1F") is 0kw_get_int()¶
Reads an integer. A number is read and truncated toward zero, as the C cast
does. Any other value gives the default back, as an integer (parseInt()), and
writes a log error (“path MUST BE a json integer”) with or without
KW_REQUIRED, as in C. With KW_WILD_NUMBER the function also reads a boolean
(1 or 0), a string (as C’s strtoll() with base 0: "0x1F" is 31, "017"
is 15, "12abc" is 12, "abc" is 0) and null (0); a list or a dict then
gives 0 and a log error (“path MUST BE a simple json element”).
KW_EXTRACT deletes the key only when the function gives its value back.
Before gobj-js 7.25.4, KW_EXTRACT deleted the key before the type check (a
value that was not a number was lost), a value of another type was logged
only with KW_REQUIRED, KW_WILD_NUMBER had no effect, and a number went
through parseInt(), which reads 1e-7 as 1.
kw_get_int(gobj, {port: 8080}, "port", 0, 0); // 8080
kw_get_int(gobj, {x: 3.9}, "x", 0, 0); // 3
kw_get_int(gobj, {}, "port", 80, 0); // 80 (the default)
kw_get_int(gobj, {port: "8080"}, "port", 80, 0); // 80, and logged: a string is not a number
kw_get_int(gobj, {port: "8080"}, "port", 80, kw_flag_t.KW_WILD_NUMBER); // 8080
kw_get_int(gobj, {mask: "0x1F"}, "mask", 0, kw_flag_t.KW_WILD_NUMBER); // 31
let kw = {port: "8080"};
kw_get_int(gobj, kw, "port", 80, kw_flag_t.KW_EXTRACT); // 80, logged; kw is still {port: "8080"}
kw = {port: 8080};
kw_get_int(gobj, kw, "port", 80, kw_flag_t.KW_EXTRACT); // 8080; kw is now {}kw_get_real()¶
Reads a real number. A number is read as it is. Any other value gives the
default back, as a number (Number()), and writes a log error (“path MUST BE a
json real”) with or without KW_REQUIRED, as in C. With KW_WILD_NUMBER the
function also reads a boolean (1 or 0), a string (as parseFloat() reads
it; 0 when the string does not start with a number) and null (0); a list or
a dict then gives 0 and a log error (“path MUST BE a simple json element”).
KW_EXTRACT deletes the key only when the function gives its value back.
Before gobj-js 7.25.4 it did not keep these rules, as kw_get_int().
kw_get_real(gobj, {t: 21.5}, "t", 0, 0); // 21.5
kw_get_real(gobj, {t: "21.5"}, "t", 0, 0); // 0, and logged: a string is not a number
kw_get_real(gobj, {t: "21.5"}, "t", 0, kw_flag_t.KW_WILD_NUMBER); // 21.5
kw_get_real(gobj, {t: null}, "t", 1, kw_flag_t.KW_WILD_NUMBER); // 0kw_get_str()¶
Reads a string. If the key has a string, you get that string. If the key is
not there, or its value is not a string, you get the default as you gave
it, as in C. Before gobj-js 7.25.1 the function put the default through
String(), so a default of 0 or null came back as "0" or "null", and
an if() on the result was true.
What it logs is what C logs:
A value that is there and is not a string (a number, a boolean, a dict, a list) writes a log error, “path MUST BE a json str”, with or without
KW_REQUIRED. To read a value that can be a number, usekw_get_int()orkw_get_dict_value(), not this function.A
nullvalue writes no log, with or withoutKW_REQUIRED: the key is there and says “no string”.With
KW_REQUIRED, a path that is not there writes a log error, “path not found”.
Before gobj-js 7.25.5 a value of another type was logged only with
KW_REQUIRED, and then a null value was logged too.
With KW_CREATE, a string default is written into the kw. Any other default
is written as null. With KW_EXTRACT only a string is deleted from the kw;
before gobj-js 7.25.4 the key was deleted before the type check, so a value
that was not a string was lost. (The C kw_get_str() does not extract at all:
its answer would point into the freed json. A JS string does not have that
problem.)
kw_get_str(gobj, {name: "x"}, "name", "", 0); // "x"
kw_get_str(gobj, {}, "name", "", 0); // ""
kw_get_str(gobj, {}, "name", null, 0); // null (not "null")
kw_get_str(gobj, {name: 5}, "name", "none", 0); // "none", and logged: 5 is not a string
kw_get_str(gobj, {name: null}, "name", "none", kw_flag_t.KW_REQUIRED); // "none", not logged
kw_get_str(gobj, {}, "name", "none", kw_flag_t.KW_REQUIRED); // "none", logged: path not found
let kw = {name: 5};
kw_get_str(gobj, kw, "name", "none", kw_flag_t.KW_EXTRACT); // "none", logged; kw is still {name: 5}kw_get_dict()¶
Reads an object. An object found is given back as it is (the same object, not
a copy). Anything else gives the default back as you gave it, null included.
As in C, a value of a different type is logged only with KW_REQUIRED
(“path MUST BE a json dict”).
Before gobj-js 7.25.2 the default went through Object(), so a null default
came back as {}, and a 0 as a Number object.
kw_get_dict(gobj, {cfg: {a: 1}}, "cfg", {}, 0); // {a: 1}, the object in the kw
kw_get_dict(gobj, {}, "cfg", null, 0); // null (not {})
kw_get_dict(gobj, {cfg: [1]}, "cfg", null, 0); // null: a list is not a dict
kw_get_dict(gobj, {cfg: [1]}, "cfg", null, kw_flag_t.KW_REQUIRED); // null, logged: path MUST BE a json dict
let kw = {};
kw_get_dict(gobj, kw, "a`b", {}, kw_flag_t.KW_CREATE); // {} -- and kw is now {a: {b: {}}}kw_get_dict_value()¶
Reads a value of any type from an object.
kw_get_list()¶
Reads an array. An array found is given back as it is. Anything else gives the
default back as you gave it; as in C, a value of a different type is logged
only with KW_REQUIRED (“path MUST BE a json list”). Before gobj-js 7.25.2
the answer went through Array(), which wraps its argument: a list found
came back inside another list, a default of [] as [[]], and a default of
null as [null].
kw_get_list(gobj, {ids: [1, 2]}, "ids", [], 0); // [1, 2] (was [[1, 2]])
kw_get_list(gobj, {}, "ids", [], 0); // [] (was [[]])
kw_get_list(gobj, {}, "ids", null, 0); // null (was [null])
kw_get_list(gobj, {ids: 5}, "ids", null, 0); // null: 5 is not a listkw_get_pointer()¶
Reads a value that is not JSON, such as a gobj or a DOM node.
Match and filter¶
kw_match_simple(kw, jn_filter)¶
Tells if kw matches a filter. It compares strings and numbers only. An empty
filter matches everything. It takes no gobj.
kw_select(gobj, kw, jn_filter, match_fn)¶
Gives a new list with a deep copy of each row that matches the filter. Use
it when the caller changes the rows. With match_fn empty the function uses
kw_match_simple().
kw_collect(gobj, kw, jn_filter, match_fn)¶
Gives a new list with a reference to each row that matches the filter. It is
kw_select() without the copy, so a change to a row changes
the source.
kw_find_json_in_list(gobj, kw_list, item, flag)¶
Gives the index of a simple JSON item in a list. Returns -1 when the list does
not hold it.
kw_clone_by_keys(gobj, kw, keys, verbose)¶
Gives a new object with the keys that keys names. keys can be a string, an
array of strings or an object. It is not a deep copy. With empty keys the
function gives kw back.
kw_clone_by_not_keys(gobj, kw, keys, verbose)¶
Gives a new object without the keys that keys names. It is the opposite of
kw_clone_by_keys().
Local storage¶
These three helpers put a value in the local storage of the browser. The persistent attributes use them. See Persistence.
kw_get_local_storage_value(key, default_value, create)¶
Reads an attribute from the local storage. With create set to true the
function writes the default value when the key does not exist.
kw_set_local_storage_value(key, value)¶
Writes an attribute to the local storage. Returns 0 on success, and -1 when
the value did not reach the store. An older version returned nothing and only
wrote to the console, so no caller saw the failure.
kw_remove_local_storage_value(key)¶
Deletes an attribute from the local storage.
kwid record helpers¶
A kwid is a collection of records. It can be a list of strings, a list of
objects, or an object of objects with the identifier as its key. These helpers
read the three forms in the same way.
kwid_match_id(ids, id)¶
Tells if id is in the collection ids. An empty ids matches every
identifier, because no filter lets everything through.
kwid_collect(gobj, kw, ids, jn_filter, match_fn)¶
Gives a new list with the records that match both ids and the filter. With
match_fn empty the function uses kw_match_simple().
kwid_find_one_record(gobj, kw, ids, jn_filter, match_fn)¶
Gives the first record that matches. It takes the parameters of
kwid_collect().
kwid_new_dict(gobj, kw, path)¶
Builds an object of objects from a list of records, with the field id of each
record as the key. With a path that is not empty the function reads the list
at that path first. The function gives an unchanged result for a kw that is
an object already.
kwid_new_list(gobj, kw, path)¶
Builds a list of records from an object of records, and writes the KEY of each
record into the record as its id. With a path that is not empty the
function reads the object at that path first. The function gives the same list
back for a kw that is a list already.
This is the normalizing half of the pair: whatever shape the data arrives in,
what comes back is the shape a table indexed and sorted by id wants.
kwid_new_list(gobj, {a: {n: 1}, b: {n: 2}});
// [{id: "a", n: 1}, {id: "b", n: 2}]kwid_get_ids(gobj, ids)¶
Gives the list of the identifiers of a collection. It accepts a string, a list of strings, a list of records or an object of records.
Inter-event metadata¶
The inter-event protocol carries its metadata inside the kw, in the key
__md_iev__. Read and write it with these helpers and never by hand: the key
name is an internal detail, and a message that goes to a remote yuno and comes
back keeps only what these helpers wrote.
msg_iev_write_key(kw, key, value)¶
Writes a key in the metadata of the message, and creates the metadata object
when it does not exist. It takes no gobj.
msg_iev_read_key(kw, key)¶
Reads a key of the metadata. Returns undefined when the message has no
metadata. It takes no gobj.
msg_iev_push_stack(gobj, kw, stack, jn_data)¶
Puts jn_data on a stack with a name inside the metadata. The stack carries the
data of one hop when a message goes through more than one yuno.
msg_iev_get_stack(gobj, kw, stack, verbose)¶
Reads the top of a stack with a name. It does not take the element out.
msg_iev_set_msg_type(gobj, kw, msg_type)¶
Writes the type of the message. An empty string deletes the key. Returns 0.
msg_iev_get_msg_type(gobj, kw)¶
Reads the type of the message. Returns an empty string when the message has none.
Metadata and private keys¶
is_metadata_key(key)¶
Tells if a key is a metadata key. A metadata key begins with two underscores.
is_private_key(key)¶
Tells if a key is a private key. A private key begins with one underscore.