@yuneta/gobj-js 7.13.7 → 7.16.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/dist/gobj-js.cjs.js +245 -6
- package/dist/gobj-js.cjs.js.map +1 -1
- package/dist/gobj-js.cjs.min.js +701 -590
- package/dist/gobj-js.cjs.min.js.map +1 -1
- package/dist/gobj-js.es.js +240 -7
- package/dist/gobj-js.es.js.map +1 -1
- package/dist/gobj-js.es.min.js +956 -840
- package/dist/gobj-js.es.min.js.map +1 -1
- package/dist/gobj-js.iife.js +245 -6
- package/dist/gobj-js.iife.js.map +1 -1
- package/dist/gobj-js.iife.min.js +720 -609
- package/dist/gobj-js.iife.min.js.map +1 -1
- package/dist/gobj-js.umd.js +245 -6
- package/dist/gobj-js.umd.js.map +1 -1
- package/dist/gobj-js.umd.min.js +720 -609
- package/dist/gobj-js.umd.min.js.map +1 -1
- package/package.json +1 -1
package/dist/gobj-js.umd.js
CHANGED
|
@@ -2300,7 +2300,9 @@
|
|
|
2300
2300
|
gobj.current_state = new_state;
|
|
2301
2301
|
let tracea = is_machine_tracing(gobj, "EV_STATE_CHANGED");
|
|
2302
2302
|
let tracea_states = __trace_gobj_states__(gobj) ? true : false;
|
|
2303
|
-
if (tracea || tracea_states)
|
|
2303
|
+
if (tracea || tracea_states) {
|
|
2304
|
+
if (__trace_machine_format__ === 1) {} else trace_machine(sprintf("🔀🔀 mach(%s%s^%s), new st(%s), prev st(%s)", !gobj.running ? "!!" : "", gobj_gclass_name(gobj), gobj_name(gobj), gobj_current_state(gobj), gobj.last_state.state_name));
|
|
2305
|
+
}
|
|
2304
2306
|
return true;
|
|
2305
2307
|
}
|
|
2306
2308
|
/***************************************************************************
|
|
@@ -2493,7 +2495,8 @@
|
|
|
2493
2495
|
if (dst.gclass.gmt.mt_inject_event) {
|
|
2494
2496
|
__inside__--;
|
|
2495
2497
|
if (tracea) {
|
|
2496
|
-
trace_machine(sprintf("
|
|
2498
|
+
if (__trace_machine_format__ === 1) trace_machine(sprintf("🔜 %s %s%s %s", event ? event : "", !dst.running ? "!!" : "", gobj_short_name(dst), state.state_name));
|
|
2499
|
+
else trace_machine(sprintf("🔃 mach(%s%s), st: %s, ev: %s, from(%s%s)", !dst.running ? "!!" : "", gobj_short_name(dst), state.state_name, event ? event : "", src && !src.running ? "!!" : "", gobj_short_name(src)));
|
|
2497
2500
|
if (kw) {
|
|
2498
2501
|
if (tracea > 1) {
|
|
2499
2502
|
if (json_object_size(kw)) trace_json(kw);
|
|
@@ -2874,8 +2877,9 @@
|
|
|
2874
2877
|
}
|
|
2875
2878
|
let tracea = __yuno__ && gobj_read_bool_attr(__yuno__, "trace_subscriptions");
|
|
2876
2879
|
if (tracea) {
|
|
2877
|
-
trace_machine(sprintf("🔝🔝
|
|
2878
|
-
|
|
2880
|
+
if (__trace_machine_format__ === 1) trace_machine(sprintf("🔝🔝 %s %s%s %s", event ? event : "", !publisher.running ? "!!" : "", gobj_short_name(publisher), publisher.current_state.state_name));
|
|
2881
|
+
else trace_machine(sprintf("🔝🔝 mach(%s%s^%s), st: %s, ev: %s%s%s", !publisher.running ? "!!" : "", gobj_gclass_name(publisher), gobj_name(publisher), publisher.current_state.state_name, "", event ? event : "", ""));
|
|
2882
|
+
if (json_object_size(kw)) trace_json(kw);
|
|
2879
2883
|
}
|
|
2880
2884
|
if (publisher.gclass.gmt.mt_publish_event) {
|
|
2881
2885
|
let topublish = publisher.gclass.gmt.mt_publish_event(publisher, event, kw);
|
|
@@ -2922,8 +2926,9 @@
|
|
|
2922
2926
|
if (__config__) {}
|
|
2923
2927
|
if (__global__) json_object_update(kw2publish, __global__);
|
|
2924
2928
|
if (tracea) {
|
|
2925
|
-
trace_machine(sprintf("🔝🔄
|
|
2926
|
-
|
|
2929
|
+
if (__trace_machine_format__ === 1) trace_machine(sprintf("🔝🔄 %s (%s) %s%s", event ? event : "", event ? event : "", !subscriber.running ? "!!" : "", gobj_short_name(subscriber)));
|
|
2930
|
+
else trace_machine(sprintf("🔝🔄 mach(%s%s), st: %s, ev: %s, from(%s%s)", !subscriber.running ? "!!" : "", gobj_short_name(subscriber), gobj_current_state(subscriber), event ? event : "", publisher && !publisher.running ? "!!" : "", gobj_short_name(publisher)));
|
|
2931
|
+
if (json_object_size(kw2publish)) trace_json(kw2publish);
|
|
2927
2932
|
}
|
|
2928
2933
|
let ret_ = gobj_send_event(subscriber, event, kw2publish, publisher);
|
|
2929
2934
|
if (ret_ < 0 && subs_flag & subs_flag_t.__own_event__) {
|
|
@@ -5098,6 +5103,234 @@
|
|
|
5098
5103
|
}
|
|
5099
5104
|
return result;
|
|
5100
5105
|
}
|
|
5106
|
+
/***************************************
|
|
5107
|
+
* Flat json (id -> value)
|
|
5108
|
+
***************************************/
|
|
5109
|
+
/************************************************************
|
|
5110
|
+
* THE FLAT FORM, AND WHY IT IS SHAPED LIKE THIS
|
|
5111
|
+
*
|
|
5112
|
+
* A json seen as a table: one row per LEAF, the id being the
|
|
5113
|
+
* PATH of the item and the value its value. Easier to store,
|
|
5114
|
+
* to compare and to diff than the nested form, and the only
|
|
5115
|
+
* one a person can read when two configurations disagree.
|
|
5116
|
+
*
|
|
5117
|
+
* {a: {b: 1}, c: [10, 20]}
|
|
5118
|
+
* -> {"a`b": 1, "c`[0]": 10, "c`[1]": 20}
|
|
5119
|
+
*
|
|
5120
|
+
* Same grammar as the C side (kwid.c), because the point is
|
|
5121
|
+
* that a flat json written by either can be read by the other:
|
|
5122
|
+
*
|
|
5123
|
+
* - segments joined by '`', the SDK's own path delimiter;
|
|
5124
|
+
* - a literal '`' in a key is DOUBLED, so no key is
|
|
5125
|
+
* forbidden -- a dict keyed by "1630" is a dict, not an
|
|
5126
|
+
* array of 1631 elements, which is what the first C
|
|
5127
|
+
* implementation answered;
|
|
5128
|
+
* - an array index is '[N]', canonical, no leading zeros;
|
|
5129
|
+
* - a dict key starting with '[' doubles it ('[[0]'), so it
|
|
5130
|
+
* can never be read as an index;
|
|
5131
|
+
* - AN EMPTY CONTAINER IS A LEAF: {} and [] hold no leaves,
|
|
5132
|
+
* and 'properties': {} is everywhere in our configs.
|
|
5133
|
+
*
|
|
5134
|
+
* flat2json() THROWS instead of guessing: an id used as leaf and
|
|
5135
|
+
* as container would depend on the order the ids are read in.
|
|
5136
|
+
************************************************************/
|
|
5137
|
+
var FLAT_MAX_DEPTH = 256;
|
|
5138
|
+
var FLAT_MAX_INDEX = 1e5;
|
|
5139
|
+
/************************************************************
|
|
5140
|
+
* Is this raw segment an array index, '[N]'?
|
|
5141
|
+
* Returns the index, or null.
|
|
5142
|
+
************************************************************/
|
|
5143
|
+
function flat_seg_index(seg) {
|
|
5144
|
+
if (typeof seg !== "string" || seg.length < 3 || seg[0] !== "[") return null;
|
|
5145
|
+
if (seg[seg.length - 1] !== "]") return null;
|
|
5146
|
+
const body = seg.slice(1, -1);
|
|
5147
|
+
if (!/^[0-9]+$/.test(body)) return null;
|
|
5148
|
+
if (body.length > 1 && body[0] === "0") return null;
|
|
5149
|
+
return parseInt(body, 10);
|
|
5150
|
+
}
|
|
5151
|
+
/************************************************************
|
|
5152
|
+
* Escape one dict key.
|
|
5153
|
+
************************************************************/
|
|
5154
|
+
function flat_escape_key(key) {
|
|
5155
|
+
const s = String(key).replace(/`/g, "``");
|
|
5156
|
+
return s[0] === "[" ? "[" + s : s;
|
|
5157
|
+
}
|
|
5158
|
+
/************************************************************
|
|
5159
|
+
* Compose a flat id from its segments.
|
|
5160
|
+
*
|
|
5161
|
+
* A STRING segment is a dict key and gets escaped; a NUMBER is
|
|
5162
|
+
* an array index and is written '[N]'. They are two types and
|
|
5163
|
+
* not two spellings: as strings, the key "[0]" and the index 0
|
|
5164
|
+
* would both be "[0]", which is the ambiguity '[N]' removes.
|
|
5165
|
+
************************************************************/
|
|
5166
|
+
function flat_key_join(segments) {
|
|
5167
|
+
if (!Array.isArray(segments) || segments.length === 0) return "";
|
|
5168
|
+
return segments.map((seg) => typeof seg === "number" ? `[${seg}]` : flat_escape_key(seg)).join("`");
|
|
5169
|
+
}
|
|
5170
|
+
/************************************************************
|
|
5171
|
+
* Split a flat id into its segments, undoing the escapes.
|
|
5172
|
+
*
|
|
5173
|
+
* An index comes back as a NUMBER and a dict key as a STRING.
|
|
5174
|
+
************************************************************/
|
|
5175
|
+
function flat_key_split(key) {
|
|
5176
|
+
if (typeof key !== "string") return null;
|
|
5177
|
+
let raw = [];
|
|
5178
|
+
let cur = "";
|
|
5179
|
+
for (let i = 0; i < key.length; i++) {
|
|
5180
|
+
if (key[i] === "`") {
|
|
5181
|
+
if (key[i + 1] === "`") {
|
|
5182
|
+
cur += "`";
|
|
5183
|
+
i++;
|
|
5184
|
+
continue;
|
|
5185
|
+
}
|
|
5186
|
+
raw.push(cur);
|
|
5187
|
+
cur = "";
|
|
5188
|
+
continue;
|
|
5189
|
+
}
|
|
5190
|
+
cur += key[i];
|
|
5191
|
+
}
|
|
5192
|
+
raw.push(cur);
|
|
5193
|
+
return raw.map((seg) => {
|
|
5194
|
+
const idx = flat_seg_index(seg);
|
|
5195
|
+
if (idx !== null) return idx;
|
|
5196
|
+
if (seg[0] === "[" && seg[1] === "[") return seg.slice(1);
|
|
5197
|
+
return seg;
|
|
5198
|
+
});
|
|
5199
|
+
}
|
|
5200
|
+
/************************************************************
|
|
5201
|
+
* Nested -> flat.
|
|
5202
|
+
************************************************************/
|
|
5203
|
+
function json2flat(jn) {
|
|
5204
|
+
const flat = {};
|
|
5205
|
+
const walk = (value, path, depth) => {
|
|
5206
|
+
if (depth > FLAT_MAX_DEPTH) throw new Error(`json2flat: deeper than ${FLAT_MAX_DEPTH}`);
|
|
5207
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
5208
|
+
const keys = Object.keys(value);
|
|
5209
|
+
if (keys.length > 0) {
|
|
5210
|
+
for (const key of keys) {
|
|
5211
|
+
const seg = flat_escape_key(key);
|
|
5212
|
+
walk(value[key], depth === 0 ? seg : path + "`" + seg, depth + 1);
|
|
5213
|
+
}
|
|
5214
|
+
return;
|
|
5215
|
+
}
|
|
5216
|
+
} else if (Array.isArray(value) && value.length > 0) {
|
|
5217
|
+
value.forEach((child, index) => {
|
|
5218
|
+
const seg = `[${index}]`;
|
|
5219
|
+
walk(child, depth === 0 ? seg : path + "`" + seg, depth + 1);
|
|
5220
|
+
});
|
|
5221
|
+
return;
|
|
5222
|
+
}
|
|
5223
|
+
if (depth === 0) return;
|
|
5224
|
+
flat[path] = value;
|
|
5225
|
+
};
|
|
5226
|
+
if (jn === void 0 || jn === null) return flat;
|
|
5227
|
+
walk(jn, "", 0);
|
|
5228
|
+
return flat;
|
|
5229
|
+
}
|
|
5230
|
+
/************************************************************
|
|
5231
|
+
* Flat -> nested. Throws on the FIRST id that does not fit:
|
|
5232
|
+
* rebuilding "most of it" is how a configuration comes back
|
|
5233
|
+
* subtly different from the one that was saved.
|
|
5234
|
+
************************************************************/
|
|
5235
|
+
function flat2json(flat) {
|
|
5236
|
+
if (flat === null || typeof flat !== "object" || Array.isArray(flat)) throw new Error("flat2json: a flat json is an object of id -> value");
|
|
5237
|
+
let root = null;
|
|
5238
|
+
for (const key of Object.keys(flat)) {
|
|
5239
|
+
const segments = flat_key_split(key);
|
|
5240
|
+
if (!segments || segments.length === 0) throw new Error(`flat2json: malformed flat id: '${key}'`);
|
|
5241
|
+
if (segments.length > FLAT_MAX_DEPTH) throw new Error(`flat2json: '${key}' deeper than ${FLAT_MAX_DEPTH}`);
|
|
5242
|
+
const first_is_index = typeof segments[0] === "number";
|
|
5243
|
+
if (root === null) root = first_is_index ? [] : {};
|
|
5244
|
+
else if (first_is_index !== Array.isArray(root)) throw new Error(`flat2json: '${key}' does not fit a ${Array.isArray(root) ? "array" : "object"} root`);
|
|
5245
|
+
let current = root;
|
|
5246
|
+
for (let i = 0; i < segments.length; i++) {
|
|
5247
|
+
const seg = segments[i];
|
|
5248
|
+
const is_index = typeof seg === "number";
|
|
5249
|
+
const is_last = i === segments.length - 1;
|
|
5250
|
+
const next_is_index = is_last ? false : typeof segments[i + 1] === "number";
|
|
5251
|
+
if (is_index && seg > FLAT_MAX_INDEX) throw new Error(`flat2json: array index ${seg} over the limit (${FLAT_MAX_INDEX}) in '${key}'`);
|
|
5252
|
+
if (is_index !== Array.isArray(current)) throw new Error(`flat2json: '${key}' uses a ${is_index ? "array index" : "key"} where the tree already has a ${Array.isArray(current) ? "array" : "object"}`);
|
|
5253
|
+
if (is_last) {
|
|
5254
|
+
if (Array.isArray(current)) {
|
|
5255
|
+
while (current.length <= seg) current.push(null);
|
|
5256
|
+
current[seg] = flat[key];
|
|
5257
|
+
} else {
|
|
5258
|
+
if (Object.prototype.hasOwnProperty.call(current, seg)) throw new Error(`flat2json: '${key}' is written twice, or once as a value and once as a container`);
|
|
5259
|
+
current[seg] = flat[key];
|
|
5260
|
+
}
|
|
5261
|
+
break;
|
|
5262
|
+
}
|
|
5263
|
+
let child;
|
|
5264
|
+
if (Array.isArray(current)) {
|
|
5265
|
+
while (current.length <= seg) current.push(null);
|
|
5266
|
+
child = current[seg];
|
|
5267
|
+
if (child === null || child === void 0) {
|
|
5268
|
+
child = next_is_index ? [] : {};
|
|
5269
|
+
current[seg] = child;
|
|
5270
|
+
}
|
|
5271
|
+
} else {
|
|
5272
|
+
child = current[seg];
|
|
5273
|
+
if (child === void 0) {
|
|
5274
|
+
child = next_is_index ? [] : {};
|
|
5275
|
+
current[seg] = child;
|
|
5276
|
+
}
|
|
5277
|
+
}
|
|
5278
|
+
if (child === null || typeof child !== "object") throw new Error(`flat2json: '${key}' walks through a value: the same id is a leaf and a container at once`);
|
|
5279
|
+
if (next_is_index !== Array.isArray(child)) throw new Error(`flat2json: '${key}' needs a ${next_is_index ? "array" : "object"} where the tree already has a ${Array.isArray(child) ? "array" : "object"}`);
|
|
5280
|
+
current = child;
|
|
5281
|
+
}
|
|
5282
|
+
}
|
|
5283
|
+
return root === null ? {} : root;
|
|
5284
|
+
}
|
|
5285
|
+
/************************************************************
|
|
5286
|
+
* Deep equality, for comparing two leaf values.
|
|
5287
|
+
************************************************************/
|
|
5288
|
+
function flat_value_equal(a, b) {
|
|
5289
|
+
if (a === b) return true;
|
|
5290
|
+
if (a === null || b === null || typeof a !== "object" || typeof b !== "object") return false;
|
|
5291
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
5292
|
+
}
|
|
5293
|
+
/************************************************************
|
|
5294
|
+
* What changed between two flat dicts:
|
|
5295
|
+
*
|
|
5296
|
+
* {added: {id: value}, removed: {id: value},
|
|
5297
|
+
* changed: {id: {from, to}}}
|
|
5298
|
+
************************************************************/
|
|
5299
|
+
function flat_diff(flat1, flat2) {
|
|
5300
|
+
const a = flat1 && typeof flat1 === "object" ? flat1 : {};
|
|
5301
|
+
const b = flat2 && typeof flat2 === "object" ? flat2 : {};
|
|
5302
|
+
const diff = {
|
|
5303
|
+
added: {},
|
|
5304
|
+
removed: {},
|
|
5305
|
+
changed: {}
|
|
5306
|
+
};
|
|
5307
|
+
for (const key of Object.keys(a)) if (!Object.prototype.hasOwnProperty.call(b, key)) diff.removed[key] = a[key];
|
|
5308
|
+
else if (!flat_value_equal(a[key], b[key])) diff.changed[key] = {
|
|
5309
|
+
from: a[key],
|
|
5310
|
+
to: b[key]
|
|
5311
|
+
};
|
|
5312
|
+
for (const key of Object.keys(b)) if (!Object.prototype.hasOwnProperty.call(a, key)) diff.added[key] = b[key];
|
|
5313
|
+
return diff;
|
|
5314
|
+
}
|
|
5315
|
+
/************************************************************
|
|
5316
|
+
* Apply that diff to a flat dict, which is MUTATED.
|
|
5317
|
+
*
|
|
5318
|
+
* On the flat form on purpose: there an id addresses one value,
|
|
5319
|
+
* so applying is setting and deleting, with nothing to walk and
|
|
5320
|
+
* nothing to guess. Nested is json2flat -> flat_apply -> flat2json.
|
|
5321
|
+
************************************************************/
|
|
5322
|
+
function flat_apply(flat, diff) {
|
|
5323
|
+
if (flat === null || typeof flat !== "object" || Array.isArray(flat)) throw new Error("flat_apply: a flat json is an object of id -> value");
|
|
5324
|
+
if (diff === null || typeof diff !== "object") throw new Error("flat_apply: a diff is the object flat_diff() answers");
|
|
5325
|
+
for (const key of Object.keys(diff.removed || {})) delete flat[key];
|
|
5326
|
+
for (const key of Object.keys(diff.added || {})) flat[key] = diff.added[key];
|
|
5327
|
+
for (const key of Object.keys(diff.changed || {})) {
|
|
5328
|
+
const change = diff.changed[key];
|
|
5329
|
+
if (!change || !Object.prototype.hasOwnProperty.call(change, "to")) throw new Error(`flat_apply: changed '${key}' without a 'to'`);
|
|
5330
|
+
flat[key] = change.to;
|
|
5331
|
+
}
|
|
5332
|
+
return flat;
|
|
5333
|
+
}
|
|
5101
5334
|
//#endregion
|
|
5102
5335
|
//#region src/dbsimple.js
|
|
5103
5336
|
/*********************************************************************************
|
|
@@ -6680,6 +6913,11 @@
|
|
|
6680
6913
|
exports.empty_string = empty_string;
|
|
6681
6914
|
exports.escapeHtml = escapeHtml;
|
|
6682
6915
|
exports.event_flag_t = event_flag_t;
|
|
6916
|
+
exports.flat2json = flat2json;
|
|
6917
|
+
exports.flat_apply = flat_apply;
|
|
6918
|
+
exports.flat_diff = flat_diff;
|
|
6919
|
+
exports.flat_key_join = flat_key_join;
|
|
6920
|
+
exports.flat_key_split = flat_key_split;
|
|
6683
6921
|
exports.gclass_add_ev_action = gclass_add_ev_action;
|
|
6684
6922
|
exports.gclass_add_event_type = gclass_add_event_type;
|
|
6685
6923
|
exports.gclass_add_state = gclass_add_state;
|
|
@@ -6807,6 +7045,7 @@
|
|
|
6807
7045
|
exports.jdb_get_topic = jdb_get_topic;
|
|
6808
7046
|
exports.jdb_init = jdb_init;
|
|
6809
7047
|
exports.jdb_update = jdb_update;
|
|
7048
|
+
exports.json2flat = json2flat;
|
|
6810
7049
|
exports.json_array_append = json_array_append;
|
|
6811
7050
|
exports.json_array_append_new = json_array_append_new;
|
|
6812
7051
|
exports.json_array_extend = json_array_extend;
|