1730 lines
61 KiB
JavaScript
1730 lines
61 KiB
JavaScript
|
|
var __extends = (this && this.__extends) || (function () {
|
||
|
|
var extendStatics = function (d, b) {
|
||
|
|
extendStatics = Object.setPrototypeOf ||
|
||
|
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||
|
|
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
||
|
|
return extendStatics(d, b);
|
||
|
|
};
|
||
|
|
return function (d, b) {
|
||
|
|
if (typeof b !== "function" && b !== null)
|
||
|
|
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
||
|
|
extendStatics(d, b);
|
||
|
|
function __() { this.constructor = d; }
|
||
|
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||
|
|
};
|
||
|
|
})();
|
||
|
|
/*
|
||
|
|
This file is part of »bacterio-plankton:base«.
|
||
|
|
|
||
|
|
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||
|
|
<info@greenscale.de>
|
||
|
|
|
||
|
|
»bacterio-plankton:base« is free software: you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU Lesser General Public License as published by
|
||
|
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
»bacterio-plankton:base« is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU Lesser General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU Lesser General Public License
|
||
|
|
along with »bacterio-plankton:base«. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
// }
|
||
|
|
/*
|
||
|
|
This file is part of »bacterio-plankton:base«.
|
||
|
|
|
||
|
|
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||
|
|
<info@greenscale.de>
|
||
|
|
|
||
|
|
»bacterio-plankton:base« is free software: you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU Lesser General Public License as published by
|
||
|
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
»bacterio-plankton:base« is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU Lesser General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU Lesser General Public License
|
||
|
|
along with »bacterio-plankton:base«. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
;
|
||
|
|
var lib_plankton;
|
||
|
|
(function (lib_plankton) {
|
||
|
|
var base;
|
||
|
|
(function (base) {
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function environment() {
|
||
|
|
return "node";
|
||
|
|
}
|
||
|
|
base.environment = environment;
|
||
|
|
})(base = lib_plankton.base || (lib_plankton.base = {}));
|
||
|
|
})(lib_plankton || (lib_plankton = {}));
|
||
|
|
/*
|
||
|
|
This file is part of »bacterio-plankton:base«.
|
||
|
|
|
||
|
|
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||
|
|
<info@greenscale.de>
|
||
|
|
|
||
|
|
»bacterio-plankton:base« is free software: you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU Lesser General Public License as published by
|
||
|
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
»bacterio-plankton:base« is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU Lesser General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU Lesser General Public License
|
||
|
|
along with »bacterio-plankton:base«. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
/*export*/ function pseudopointer_null() {
|
||
|
|
return {
|
||
|
|
"value": null
|
||
|
|
};
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
/*export*/ function pseudopointer_make(value) {
|
||
|
|
return {
|
||
|
|
"value": value
|
||
|
|
};
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
/*export*/ function pseudopointer_isset(pseudopointer) {
|
||
|
|
return (pseudopointer.value != null);
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
/*export*/ function pseudopointer_read(pseudopointer) {
|
||
|
|
if (pseudopointer.value != null) {
|
||
|
|
return pseudopointer.value;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
var message = "nullpointer dereferencation";
|
||
|
|
throw (new Error(message));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
/*export*/ function pseudopointer_write(pseudopointer, value) {
|
||
|
|
pseudopointer.value = value;
|
||
|
|
}
|
||
|
|
/*
|
||
|
|
This file is part of »bacterio-plankton:base«.
|
||
|
|
|
||
|
|
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||
|
|
<info@greenscale.de>
|
||
|
|
|
||
|
|
»bacterio-plankton:base« is free software: you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU Lesser General Public License as published by
|
||
|
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
»bacterio-plankton:base« is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU Lesser General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU Lesser General Public License
|
||
|
|
along with »bacterio-plankton:base«. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
var instance_verbosity = 0;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function instance_collate(value1, value2) {
|
||
|
|
if (typeof (value1) === "object") {
|
||
|
|
if (value1 == null) {
|
||
|
|
return (value2 == null);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if ("_collate" in value1) {
|
||
|
|
return value1["_collate"](value2);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
throw (new Error("[collate]" + " " + "object has no such method"));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if (instance_verbosity >= 1) {
|
||
|
|
// lib_plankton.log.warn("[collate]" + " " + "primitive value; using default implementation");
|
||
|
|
}
|
||
|
|
return (value1 === value2);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function instance_compare(value1, value2) {
|
||
|
|
if (typeof (value1) === "object") {
|
||
|
|
if ("_compare" in value1) {
|
||
|
|
return value1["_compare"](value2);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
throw (new Error("[compare]" + " " + "object has no such method"));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if (instance_verbosity >= 1) {
|
||
|
|
// lib_plankton.log.warn("[compare]" + " " + "primitive value; using default implementation");
|
||
|
|
}
|
||
|
|
return (value1 <= value2);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function instance_clone(value) {
|
||
|
|
if (typeof (value) === "object") {
|
||
|
|
if ("_clone" in value) {
|
||
|
|
return value["_clone"]();
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
throw (new Error("[clone]" + " " + "object has no such method"));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if (instance_verbosity >= 1) {
|
||
|
|
// lib_plankton.log.warn("[clone]" + " " + "primitive value; using default implementation");
|
||
|
|
}
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @desc the ability to generate a string out of the element, which identifies it to a high degree
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function instance_hash(value) {
|
||
|
|
if (typeof (value) === "object") {
|
||
|
|
if ("_hash" in value) {
|
||
|
|
return value["_hash"]();
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
throw (new Error("[hash]" + " " + "object has no such method"));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if (instance_verbosity >= 1) {
|
||
|
|
// lib_plankton.log.warn("[hash]" + " " + "primitive value; using default implementation");
|
||
|
|
}
|
||
|
|
return String(value);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @desc the ability to map the element to a textual representation (most likely not injective)
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function instance_show(value) {
|
||
|
|
if (typeof (value) === "object") {
|
||
|
|
if (value == null) {
|
||
|
|
return "NULL";
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if ("_show" in value) {
|
||
|
|
return value["_show"]();
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
// throw (new Error("[show]" + " " + "object has no such method"));
|
||
|
|
return JSON.stringify(value);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if (instance_verbosity >= 1) {
|
||
|
|
// lib_plankton.log.warn("[show]" + " " + "primitive value; using default implementation");
|
||
|
|
}
|
||
|
|
return String(value);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/*
|
||
|
|
This file is part of »bacterio-plankton:base«.
|
||
|
|
|
||
|
|
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||
|
|
<info@greenscale.de>
|
||
|
|
|
||
|
|
»bacterio-plankton:base« is free software: you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU Lesser General Public License as published by
|
||
|
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
»bacterio-plankton:base« is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU Lesser General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU Lesser General Public License
|
||
|
|
along with »bacterio-plankton:base«. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
/**
|
||
|
|
* @author frac
|
||
|
|
*/
|
||
|
|
var class_observer = /** @class */ (function () {
|
||
|
|
/**
|
||
|
|
* @author frac
|
||
|
|
*/
|
||
|
|
function class_observer() {
|
||
|
|
this.counter = 0;
|
||
|
|
this.actions = {};
|
||
|
|
this.buffer = [];
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author frac
|
||
|
|
*/
|
||
|
|
class_observer.prototype.empty = function () {
|
||
|
|
return (Object.keys(this.actions).length == 0);
|
||
|
|
};
|
||
|
|
/**
|
||
|
|
* @author frac
|
||
|
|
*/
|
||
|
|
class_observer.prototype.flush = function () {
|
||
|
|
this.actions = {};
|
||
|
|
};
|
||
|
|
/**
|
||
|
|
* @author frac
|
||
|
|
*/
|
||
|
|
class_observer.prototype.set = function (id, action) {
|
||
|
|
this.actions[id] = action;
|
||
|
|
};
|
||
|
|
/**
|
||
|
|
* @author frac
|
||
|
|
*/
|
||
|
|
class_observer.prototype.del = function (id) {
|
||
|
|
delete this.actions[id];
|
||
|
|
};
|
||
|
|
/**
|
||
|
|
* @author frac
|
||
|
|
*/
|
||
|
|
class_observer.prototype.add = function (action) {
|
||
|
|
this.set((this.counter++).toString(), action);
|
||
|
|
};
|
||
|
|
/**
|
||
|
|
* @author frac
|
||
|
|
*/
|
||
|
|
class_observer.prototype.notify = function (information, delayed) {
|
||
|
|
var _this = this;
|
||
|
|
if (information === void 0) { information = {}; }
|
||
|
|
if (delayed === void 0) { delayed = false; }
|
||
|
|
if (delayed) {
|
||
|
|
this.buffer.push(information);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
Object.keys(this.actions).forEach(function (id) { return _this.actions[id](information); });
|
||
|
|
}
|
||
|
|
};
|
||
|
|
/**
|
||
|
|
* @author frac
|
||
|
|
*/
|
||
|
|
class_observer.prototype.rollout = function () {
|
||
|
|
var _this = this;
|
||
|
|
this.buffer.forEach(function (information) { return _this.notify(information, false); });
|
||
|
|
this.buffer = [];
|
||
|
|
};
|
||
|
|
return class_observer;
|
||
|
|
}());
|
||
|
|
/**
|
||
|
|
* @author frac
|
||
|
|
*/
|
||
|
|
/*
|
||
|
|
export interface interface_readable<type_value> {
|
||
|
|
|
||
|
|
|**
|
||
|
|
* @author frac
|
||
|
|
*|
|
||
|
|
read() : type_executor<type_value, Error>;
|
||
|
|
|
||
|
|
}
|
||
|
|
*/
|
||
|
|
/**
|
||
|
|
* @author frac
|
||
|
|
*/
|
||
|
|
/*
|
||
|
|
export interface interface_writeable<type_value> {
|
||
|
|
|
||
|
|
|**
|
||
|
|
* @author frac
|
||
|
|
*|
|
||
|
|
write(value : type_value) : type_executor<void, Error>;
|
||
|
|
|
||
|
|
}
|
||
|
|
*/
|
||
|
|
/*
|
||
|
|
This file is part of »bacterio-plankton:base«.
|
||
|
|
|
||
|
|
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||
|
|
<info@greenscale.de>
|
||
|
|
|
||
|
|
»bacterio-plankton:base« is free software: you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU Lesser General Public License as published by
|
||
|
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
»bacterio-plankton:base« is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU Lesser General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU Lesser General Public License
|
||
|
|
along with »bacterio-plankton:base«. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
/**
|
||
|
|
* @author frac
|
||
|
|
*/
|
||
|
|
var class_error = /** @class */ (function (_super) {
|
||
|
|
__extends(class_error, _super);
|
||
|
|
/**
|
||
|
|
* @author frac
|
||
|
|
*/
|
||
|
|
function class_error(message, suberrors) {
|
||
|
|
if (suberrors === void 0) { suberrors = []; }
|
||
|
|
var _this = _super.call(this, message) || this;
|
||
|
|
_this.suberrors = suberrors;
|
||
|
|
_this.mess = message;
|
||
|
|
return _this;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @override
|
||
|
|
* @author frac
|
||
|
|
*/
|
||
|
|
class_error.prototype.toString = function () {
|
||
|
|
return ( /*super.toString()*/this.mess + " " + ("[" + this.suberrors.map(function (x) { return x.toString(); }).join(",") + "]"));
|
||
|
|
};
|
||
|
|
return class_error;
|
||
|
|
}(Error));
|
||
|
|
var lib_plankton;
|
||
|
|
(function (lib_plankton) {
|
||
|
|
var base;
|
||
|
|
(function (base) {
|
||
|
|
/**
|
||
|
|
* returns the current UNIX timestamp
|
||
|
|
*
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function get_current_timestamp(rounded) {
|
||
|
|
if (rounded === void 0) { rounded = false; }
|
||
|
|
var x = (Date.now() / 1000);
|
||
|
|
return (rounded ? Math.round(x) : x);
|
||
|
|
;
|
||
|
|
}
|
||
|
|
base.get_current_timestamp = get_current_timestamp;
|
||
|
|
/**
|
||
|
|
*/
|
||
|
|
function object_merge(core, mantle) {
|
||
|
|
return Object.assign(core, mantle);
|
||
|
|
}
|
||
|
|
base.object_merge = object_merge;
|
||
|
|
})(base = lib_plankton.base || (lib_plankton.base = {}));
|
||
|
|
})(lib_plankton || (lib_plankton = {}));
|
||
|
|
/*
|
||
|
|
This file is part of »bacterio-plankton:pod«.
|
||
|
|
|
||
|
|
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||
|
|
<info@greenscale.de>
|
||
|
|
|
||
|
|
»bacterio-plankton:pod« is free software: you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU Lesser General Public License as published by
|
||
|
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
»bacterio-plankton:pod« is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU Lesser General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU Lesser General Public License
|
||
|
|
along with »bacterio-plankton:pod«. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
var lib_plankton;
|
||
|
|
(function (lib_plankton) {
|
||
|
|
var pod;
|
||
|
|
(function (pod_1) {
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function make_empty() {
|
||
|
|
return {
|
||
|
|
"kind": "empty"
|
||
|
|
};
|
||
|
|
}
|
||
|
|
pod_1.make_empty = make_empty;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function make_filled(value) {
|
||
|
|
return {
|
||
|
|
"kind": "filled",
|
||
|
|
"value": value
|
||
|
|
};
|
||
|
|
}
|
||
|
|
pod_1.make_filled = make_filled;
|
||
|
|
/**
|
||
|
|
* whether the pod is filled
|
||
|
|
*
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function is_filled(pod) {
|
||
|
|
return (pod.kind === "filled");
|
||
|
|
}
|
||
|
|
pod_1.is_filled = is_filled;
|
||
|
|
/**
|
||
|
|
* return the value, stored in the pod-wrapper
|
||
|
|
*
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function cull(pod) {
|
||
|
|
if (!is_filled(pod)) {
|
||
|
|
throw (new Error("cull from empty"));
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
return pod.value;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
pod_1.cull = cull;
|
||
|
|
/**
|
||
|
|
* to pass on a empty-pod or to use a filled-pod
|
||
|
|
*
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function propagate(pod, function_) {
|
||
|
|
if (!is_filled(pod)) {
|
||
|
|
return make_empty();
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
return make_filled(function_(pod.value));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
pod_1.propagate = propagate;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function distinguish(pod, function_empty, function_filled) {
|
||
|
|
return ((!is_filled(pod))
|
||
|
|
? function_empty()
|
||
|
|
: function_filled(pod.value));
|
||
|
|
}
|
||
|
|
pod_1.distinguish = distinguish;
|
||
|
|
/**
|
||
|
|
*/
|
||
|
|
function show(pod, options = {}) {
|
||
|
|
options = Object.assign({
|
||
|
|
"show_value": value => String(value),
|
||
|
|
}, options);
|
||
|
|
if (!is_filled(pod)) {
|
||
|
|
return "<·>";
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
return ("<- " + options.show_value(pod.value) + " ->");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
pod_1.show = show;
|
||
|
|
})(pod = lib_plankton.pod || (lib_plankton.pod = {}));
|
||
|
|
})(lib_plankton || (lib_plankton = {}));
|
||
|
|
/*
|
||
|
|
This file is part of »bacterio-plankton:pod«.
|
||
|
|
|
||
|
|
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||
|
|
<info@greenscale.de>
|
||
|
|
|
||
|
|
»bacterio-plankton:pod« is free software: you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU Lesser General Public License as published by
|
||
|
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
»bacterio-plankton:pod« is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU Lesser General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU Lesser General Public License
|
||
|
|
along with »bacterio-plankton:pod«. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
var lib_plankton;
|
||
|
|
(function (lib_plankton) {
|
||
|
|
var pod;
|
||
|
|
(function (pod) {
|
||
|
|
/**
|
||
|
|
*/
|
||
|
|
class class_pod {
|
||
|
|
constructor(subject) { this.subject = subject; }
|
||
|
|
is_empty() { return (!pod.is_filled(this.subject)); }
|
||
|
|
is_filled() { return pod.is_filled(this.subject); }
|
||
|
|
cull() { return pod.cull(this.subject); }
|
||
|
|
show(show_value = undefined) { return pod.show(this.subject, show_value); }
|
||
|
|
toString() { return this.show(); }
|
||
|
|
propagate(function_) { return new class_pod(pod.propagate(this.subject, function_)); }
|
||
|
|
distinguish(function_empty, function_filled) { return pod.distinguish(this.subject, function_empty, function_filled); }
|
||
|
|
}
|
||
|
|
pod.class_pod = class_pod;
|
||
|
|
})(pod = lib_plankton.pod || (lib_plankton.pod = {}));
|
||
|
|
})(lib_plankton || (lib_plankton = {}));
|
||
|
|
/*
|
||
|
|
This file is part of »bacterio-plankton:call«.
|
||
|
|
|
||
|
|
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||
|
|
<info@greenscale.de>
|
||
|
|
|
||
|
|
»bacterio-plankton:call« is free software: you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU Lesser General Public License as published by
|
||
|
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
»bacterio-plankton:call« is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU Lesser General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU Lesser General Public License
|
||
|
|
along with »bacterio-plankton:call«. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
"use strict";
|
||
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
|
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
|
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
|
|
});
|
||
|
|
};
|
||
|
|
var lib_plankton;
|
||
|
|
(function (lib_plankton) {
|
||
|
|
var call;
|
||
|
|
(function (call) {
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function executor_resolve(result) {
|
||
|
|
return ((resolve, reject) => resolve(result));
|
||
|
|
}
|
||
|
|
call.executor_resolve = executor_resolve;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function executor_reject(reason) {
|
||
|
|
return ((resolve, reject) => reject(reason));
|
||
|
|
}
|
||
|
|
call.executor_reject = executor_reject;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function executor_transform(executor, transform_result, transform_reason) {
|
||
|
|
return ((resolve, reject) => {
|
||
|
|
executor(result => resolve(transform_result(result)), reason => reject(transform_reason(reason)));
|
||
|
|
});
|
||
|
|
}
|
||
|
|
call.executor_transform = executor_transform;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function executor_transform_default(executor, transform_result, wrap_string = null) {
|
||
|
|
let transform_reason = (error => ((wrap_string == null) ? error : new class_error(wrap_string, [error])));
|
||
|
|
return (executor_transform(executor, transform_result, transform_reason));
|
||
|
|
}
|
||
|
|
call.executor_transform_default = executor_transform_default;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function executor_compose_sequential(first, second) {
|
||
|
|
return ((resolve, reject) => {
|
||
|
|
first(result => {
|
||
|
|
second(result)(resolve, reject);
|
||
|
|
}, reason => {
|
||
|
|
reject(reason);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
call.executor_compose_sequential = executor_compose_sequential;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function executor_chain(state, executors) {
|
||
|
|
return ((resolve, reject) => {
|
||
|
|
if (executors.length == 0) {
|
||
|
|
return resolve(state);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
return executors[0](state)(result => {
|
||
|
|
executor_chain(result, executors.slice(1))(resolve, reject);
|
||
|
|
}, reject);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
/*
|
||
|
|
*/
|
||
|
|
/*
|
||
|
|
if (executors.length == 0) {
|
||
|
|
return executor_resolve<type_state, type_error>(state);
|
||
|
|
}
|
||
|
|
else if (executors.length == 1) {
|
||
|
|
return executors[0](state);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
return (
|
||
|
|
executor_chain<type_state, type_error>(
|
||
|
|
state,
|
||
|
|
[
|
||
|
|
state => (resolve, reject) => executors[0](state)(result => executors[1](result)(resolve, reject), reject)
|
||
|
|
].concat(executors.slice(2))
|
||
|
|
)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
*/
|
||
|
|
/*
|
||
|
|
return (
|
||
|
|
executors.reduce(
|
||
|
|
(chain, current) => executor_compose_sequential<type_state, type_state, type_error>(chain, current, deferred),
|
||
|
|
executor_resolve<type_state, type_error>(state)
|
||
|
|
)
|
||
|
|
);
|
||
|
|
*/
|
||
|
|
}
|
||
|
|
call.executor_chain = executor_chain;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function executor_first(executors) {
|
||
|
|
/*
|
||
|
|
return (
|
||
|
|
(resolve, reject) => {
|
||
|
|
if (executors.length == 0) {
|
||
|
|
reject(new Error("all failed"));
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
executors[0](
|
||
|
|
result => {
|
||
|
|
resolve(result);
|
||
|
|
},
|
||
|
|
reason => {
|
||
|
|
executor_first<type_result, type_reason>(executors.slice(1))(resolve, reject);
|
||
|
|
}
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
);
|
||
|
|
*/
|
||
|
|
return ((resolve, reject) => {
|
||
|
|
executor_chain([], executors.map(executor => reasons => (resolve_, reject_) => {
|
||
|
|
executor(result => reject_(result), reason => resolve_(reasons.concat([reason])));
|
||
|
|
}))(errors => reject(errors), result => resolve(result));
|
||
|
|
});
|
||
|
|
}
|
||
|
|
call.executor_first = executor_first;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function executor_condense(executors) {
|
||
|
|
return (executor_chain([], executors.map(executor => result => (resolve, reject) => {
|
||
|
|
executor(element => resolve(result.concat([element])), reject);
|
||
|
|
})));
|
||
|
|
}
|
||
|
|
call.executor_condense = executor_condense;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
* @deprecated use condense
|
||
|
|
*/
|
||
|
|
function executor_filter(executors, predicate) {
|
||
|
|
return (executor_chain([], executors.map(executor => result => (resolve, reject) => {
|
||
|
|
executor(element => resolve(predicate(element) ? result.concat([element]) : result), reject);
|
||
|
|
})));
|
||
|
|
}
|
||
|
|
call.executor_filter = executor_filter;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
* @deprecated use condense
|
||
|
|
*/
|
||
|
|
function executor_map(executors, transformator) {
|
||
|
|
return (executor_chain([], executors.map(executor => result => (resolve, reject) => {
|
||
|
|
executor(element1 => resolve(result.concat([transformator(element1)])), reject);
|
||
|
|
})));
|
||
|
|
}
|
||
|
|
call.executor_map = executor_map;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
* @deprecated use condense
|
||
|
|
*/
|
||
|
|
function executor_reduce(executors, initial, accumulator) {
|
||
|
|
return (executor_chain(initial, executors.map(executor => result => (resolve, reject) => {
|
||
|
|
executor(element => resolve(accumulator(result, element)), reject);
|
||
|
|
})));
|
||
|
|
}
|
||
|
|
call.executor_reduce = executor_reduce;
|
||
|
|
})(call = lib_plankton.call || (lib_plankton.call = {}));
|
||
|
|
})(lib_plankton || (lib_plankton = {}));
|
||
|
|
/*
|
||
|
|
This file is part of »bacterio-plankton:call«.
|
||
|
|
|
||
|
|
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||
|
|
<info@greenscale.de>
|
||
|
|
|
||
|
|
»bacterio-plankton:call« is free software: you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU Lesser General Public License as published by
|
||
|
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
»bacterio-plankton:call« is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU Lesser General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU Lesser General Public License
|
||
|
|
along with »bacterio-plankton:call«. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
var lib_plankton;
|
||
|
|
(function (lib_plankton) {
|
||
|
|
var call;
|
||
|
|
(function (call) {
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function promise_reject(reason) {
|
||
|
|
return Promise.reject(reason);
|
||
|
|
}
|
||
|
|
call.promise_reject = promise_reject;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function promise_resolve(result) {
|
||
|
|
return Promise.resolve(result);
|
||
|
|
}
|
||
|
|
call.promise_resolve = promise_resolve;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function promise_make(executor) {
|
||
|
|
return (new Promise(executor));
|
||
|
|
}
|
||
|
|
call.promise_make = promise_make;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function promise_then_close(promise, resolver, rejector) {
|
||
|
|
promise.then(resolver, rejector);
|
||
|
|
}
|
||
|
|
call.promise_then_close = promise_then_close;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function promise_then_append(promise, resolver, rejector = null) {
|
||
|
|
if (rejector == null) {
|
||
|
|
rejector = (reason) => promise_reject(reason);
|
||
|
|
}
|
||
|
|
return (promise.then(resolver, rejector));
|
||
|
|
}
|
||
|
|
call.promise_then_append = promise_then_append;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function promise_all(promises) {
|
||
|
|
return Promise.all(promises);
|
||
|
|
}
|
||
|
|
call.promise_all = promise_all;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function promise_chain(promises, start = undefined) {
|
||
|
|
return (promises.reduce((chain, promise) => promise_then_append(chain, promise), promise_resolve(start)));
|
||
|
|
}
|
||
|
|
call.promise_chain = promise_chain;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function promise_condense(promises) {
|
||
|
|
return (promise_chain(promises.map(promise => result => promise_then_append(promise(), element => promise_resolve(result.concat([element])))), []));
|
||
|
|
}
|
||
|
|
call.promise_condense = promise_condense;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function promise_group(promises, serial = false) {
|
||
|
|
const decorate = function (promise, name) {
|
||
|
|
return (() => promise_then_append(promise(), value => promise_resolve({ "key": name, "value": value })));
|
||
|
|
};
|
||
|
|
const convert = function (array) {
|
||
|
|
let object = {};
|
||
|
|
array.forEach(({ "key": key, "value": value }) => { object[key] = value; });
|
||
|
|
return object;
|
||
|
|
};
|
||
|
|
if (serial) {
|
||
|
|
return (promise_then_append(promise_condense(Object.keys(promises)
|
||
|
|
.map(name => decorate(promises[name], name))), list => promise_resolve(convert(list))));
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
return (promise_then_append(promise_all(Object.keys(promises)
|
||
|
|
.map(name => decorate(promises[name], name))
|
||
|
|
.map(promise => promise())), list => promise_resolve(convert(list))));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
call.promise_group = promise_group;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function promise_wrap(promise, transformator_result, transformator_reason = lib_plankton.call.id) {
|
||
|
|
return (promise_make((resolve, reject) => {
|
||
|
|
promise_then_close(promise, result => resolve(transformator_result(result)), reason => reject(transformator_reason(reason)));
|
||
|
|
}));
|
||
|
|
}
|
||
|
|
call.promise_wrap = promise_wrap;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
/*
|
||
|
|
export function promise_show<type_result, type_reason>(label : string) : (result : type_result)=>type_promise<type_result, type_reason> {
|
||
|
|
return (
|
||
|
|
result => promise_make<type_result, type_reason>(
|
||
|
|
(resolve, reject) => {
|
||
|
|
// lib_plankton.log.info(label + ": " + instance_show(result));
|
||
|
|
process.stdout.write(label + ": " + instance_show(result));
|
||
|
|
resolve(result);
|
||
|
|
}
|
||
|
|
)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
*/
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
/*
|
||
|
|
export function promise_log<type_result, type_reason>(result : type_result) : (result : type_result)=>type_promise<type_result, type_reason> {
|
||
|
|
return promise_show<type_result, type_reason>("log");
|
||
|
|
}
|
||
|
|
*/
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function promise_attach(state, promise, name) {
|
||
|
|
return (promise_wrap(promise, result => {
|
||
|
|
state[name] = result;
|
||
|
|
return state;
|
||
|
|
}));
|
||
|
|
}
|
||
|
|
call.promise_attach = promise_attach;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function promise_delay(promise, delay) {
|
||
|
|
return promise_make((resolve, reject) => {
|
||
|
|
call.timeout(() => {
|
||
|
|
promise_then_close(promise, resolve, reject);
|
||
|
|
return null;
|
||
|
|
}, delay);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
call.promise_delay = promise_delay;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function promise_to_executor(promise) {
|
||
|
|
return ((resolve, reject) => promise.then(resolve, reject));
|
||
|
|
}
|
||
|
|
call.promise_to_executor = promise_to_executor;
|
||
|
|
})(call = lib_plankton.call || (lib_plankton.call = {}));
|
||
|
|
})(lib_plankton || (lib_plankton = {}));
|
||
|
|
/*
|
||
|
|
This file is part of »bacterio-plankton:call«.
|
||
|
|
|
||
|
|
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||
|
|
<info@greenscale.de>
|
||
|
|
|
||
|
|
»bacterio-plankton:call« is free software: you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU Lesser General Public License as published by
|
||
|
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
»bacterio-plankton:call« is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU Lesser General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU Lesser General Public License
|
||
|
|
along with »bacterio-plankton:call«. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
var lib_plankton;
|
||
|
|
(function (lib_plankton) {
|
||
|
|
var call;
|
||
|
|
(function (call) {
|
||
|
|
/**
|
||
|
|
*/
|
||
|
|
class CancellablePromise extends Promise {
|
||
|
|
/**
|
||
|
|
*/
|
||
|
|
constructor(executor) {
|
||
|
|
super((resolve, reject) => { });
|
||
|
|
this.subject = (new Promise((resolve, reject) => {
|
||
|
|
Promise.race([
|
||
|
|
new Promise(executor),
|
||
|
|
new Promise((resolve_, reject_) => {
|
||
|
|
this.interval = setInterval(() => {
|
||
|
|
if (!this.cancelled) {
|
||
|
|
// do nothing
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
reject_(new Error("cancelled"));
|
||
|
|
this.clear();
|
||
|
|
}
|
||
|
|
}, 0);
|
||
|
|
}),
|
||
|
|
])
|
||
|
|
.then(resolve, reject);
|
||
|
|
}));
|
||
|
|
this.cancelled = false;
|
||
|
|
this.interval = null;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
*/
|
||
|
|
clear() {
|
||
|
|
if (this.interval === null) {
|
||
|
|
// do nothing
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
clearInterval(this.interval);
|
||
|
|
this.interval = null;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
*/
|
||
|
|
then(onfulfilled, onrejected) {
|
||
|
|
this.clear();
|
||
|
|
return this.subject.then(onfulfilled, onrejected);
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
*/
|
||
|
|
catch(x) {
|
||
|
|
this.clear();
|
||
|
|
return this.subject.catch(x);
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
*/
|
||
|
|
cancel() {
|
||
|
|
this.cancelled = true;
|
||
|
|
this.clear();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
call.CancellablePromise = CancellablePromise;
|
||
|
|
})(call = lib_plankton.call || (lib_plankton.call = {}));
|
||
|
|
})(lib_plankton || (lib_plankton = {}));
|
||
|
|
/*
|
||
|
|
This file is part of »bacterio-plankton:call«.
|
||
|
|
|
||
|
|
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||
|
|
<info@greenscale.de>
|
||
|
|
|
||
|
|
»bacterio-plankton:call« is free software: you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU Lesser General Public License as published by
|
||
|
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
»bacterio-plankton:call« is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU Lesser General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU Lesser General Public License
|
||
|
|
along with »bacterio-plankton:call«. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
var lib_plankton;
|
||
|
|
(function (lib_plankton) {
|
||
|
|
var call;
|
||
|
|
(function (call) {
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
let enum_initializer_state;
|
||
|
|
(function (enum_initializer_state) {
|
||
|
|
enum_initializer_state[enum_initializer_state["initial"] = 0] = "initial";
|
||
|
|
enum_initializer_state[enum_initializer_state["waiting"] = 1] = "waiting";
|
||
|
|
enum_initializer_state[enum_initializer_state["successful"] = 2] = "successful";
|
||
|
|
enum_initializer_state[enum_initializer_state["failed"] = 3] = "failed";
|
||
|
|
})(enum_initializer_state = call.enum_initializer_state || (call.enum_initializer_state = {}));
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function initializer_make(fetcher) {
|
||
|
|
let subject = {
|
||
|
|
"fetcher": fetcher,
|
||
|
|
"state": enum_initializer_state.initial,
|
||
|
|
"queue": [],
|
||
|
|
"result": undefined,
|
||
|
|
"reason": undefined,
|
||
|
|
};
|
||
|
|
return subject;
|
||
|
|
}
|
||
|
|
call.initializer_make = initializer_make;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function initializer_actuate(subject) {
|
||
|
|
switch (subject.state) {
|
||
|
|
case enum_initializer_state.successful: {
|
||
|
|
subject.queue.forEach(entry => entry.resolve(subject.result));
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case enum_initializer_state.failed: {
|
||
|
|
subject.queue.forEach(entry => entry.reject(subject.reason));
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default: {
|
||
|
|
throw (new Error(`unhandled state ${subject.state}`));
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function initializer_reset(subject) {
|
||
|
|
subject.state = enum_initializer_state.initial;
|
||
|
|
subject.queue = [];
|
||
|
|
}
|
||
|
|
call.initializer_reset = initializer_reset;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function initializer_state(subject) {
|
||
|
|
return subject.state;
|
||
|
|
}
|
||
|
|
call.initializer_state = initializer_state;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function initializer_get(subject) {
|
||
|
|
switch (subject.state) {
|
||
|
|
case enum_initializer_state.initial: {
|
||
|
|
subject.state = enum_initializer_state.waiting;
|
||
|
|
return (call.promise_make((resolve, reject) => {
|
||
|
|
subject.queue.push({ "resolve": resolve, "reject": reject });
|
||
|
|
subject.fetcher().then(result => {
|
||
|
|
subject.state = enum_initializer_state.successful;
|
||
|
|
subject.result = result;
|
||
|
|
initializer_actuate(subject);
|
||
|
|
}, reason => {
|
||
|
|
subject.state = enum_initializer_state.failed;
|
||
|
|
subject.reason = reason;
|
||
|
|
initializer_actuate(subject);
|
||
|
|
});
|
||
|
|
}));
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case enum_initializer_state.waiting: {
|
||
|
|
return (call.promise_make((resolve, reject) => {
|
||
|
|
subject.queue.push({ "resolve": resolve, "reject": reject });
|
||
|
|
}));
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case enum_initializer_state.successful: {
|
||
|
|
return (call.promise_resolve(subject.result));
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case enum_initializer_state.failed: {
|
||
|
|
return (call.promise_reject(subject.reason));
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default: {
|
||
|
|
throw (new Error(`unhandled state ${subject.state}`));
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
call.initializer_get = initializer_get;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function initializer_get_sync(subject) {
|
||
|
|
switch (subject.state) {
|
||
|
|
case enum_initializer_state.successful: {
|
||
|
|
return subject.result;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case enum_initializer_state.failed: {
|
||
|
|
throw subject.reason;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default: {
|
||
|
|
throw (new Error(`unhandled state ${subject.state}`));
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function initializer_set_sync(subject, result) {
|
||
|
|
switch (subject.state) {
|
||
|
|
case enum_initializer_state.successful: {
|
||
|
|
subject.result = result;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case enum_initializer_state.failed: {
|
||
|
|
subject.state = enum_initializer_state.successful;
|
||
|
|
subject.result = result;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default: {
|
||
|
|
throw (new Error(`unhandled state ${subject.state}`));
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
})(call = lib_plankton.call || (lib_plankton.call = {}));
|
||
|
|
})(lib_plankton || (lib_plankton = {}));
|
||
|
|
/*
|
||
|
|
This file is part of »bacterio-plankton:call«.
|
||
|
|
|
||
|
|
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||
|
|
<info@greenscale.de>
|
||
|
|
|
||
|
|
»bacterio-plankton:call« is free software: you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU Lesser General Public License as published by
|
||
|
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
»bacterio-plankton:call« is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU Lesser General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU Lesser General Public License
|
||
|
|
along with »bacterio-plankton:call«. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
var lib_plankton;
|
||
|
|
(function (lib_plankton) {
|
||
|
|
var call;
|
||
|
|
(function (call) {
|
||
|
|
/*
|
||
|
|
The core idea of this library is to provide means for asynchronous program flow. The old-school way to do is,
|
||
|
|
is to use callbacks. While this approach is simple and easy to understand, it has some disadvantages. As an
|
||
|
|
attempt to relief and improve this, the promise-system was introduced. In principle it solves most of the
|
||
|
|
problems found in the callback-approach; however it has some downsides as well:
|
||
|
|
|
||
|
|
- Convolution of multiple principles
|
||
|
|
Promises unite the ideas of asynchronous program flow and error handling.
|
||
|
|
|
||
|
|
- Instant execution
|
||
|
|
Creating a promise results in the instant execution of the given executor prodecure. While this might be
|
||
|
|
convenient in some cases, it can be quite disturbing and counter-intuitive in others.
|
||
|
|
|
||
|
|
- Broken typing
|
||
|
|
The Promise system doesn't distinguish between an appending "then" (i.e. passing a function, which returns a
|
||
|
|
new promise) and a closing "then" (i.e. passing a function, which has no return value). On top of that it
|
||
|
|
allows returning simple values in an appending "then", which results in an implicit call of the executors
|
||
|
|
"resolve"-function. The price for these "pragmatic" features is that the whole system can't be typed well.
|
||
|
|
And even though JavaScript is not a strictly typed language, it was a quite questionable decision to design
|
||
|
|
the promise system in a way, which breaks typing from the start.
|
||
|
|
|
||
|
|
The deferral-system forseeks to solve these issues while retaining the advantages of the promise-system.
|
||
|
|
*/
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
* @desc activates the deferral and handles its output according to a given procedure
|
||
|
|
* @param {(value : type_value)=>void} procedure a function which receives the output of the deferral as argument
|
||
|
|
*/
|
||
|
|
function deferral_use(deferral, input, procedure) {
|
||
|
|
deferral.representation(input).then(value => {
|
||
|
|
procedure(value);
|
||
|
|
}, reason => {
|
||
|
|
throw reason;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
call.deferral_use = deferral_use;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
* @desc creates a deferral-subject (similar to "new Promise", where "convey" reflects "resolve"/"reject")
|
||
|
|
*/
|
||
|
|
function deferral_make(handler) {
|
||
|
|
return ({
|
||
|
|
"representation": ((input) => (new Promise((resolve, reject) => {
|
||
|
|
handler(input, resolve);
|
||
|
|
})))
|
||
|
|
});
|
||
|
|
}
|
||
|
|
call.deferral_make = deferral_make;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
* @desc wraps a simple function into a deferral (similar to "Promise.resolve"/"Promise.reject")
|
||
|
|
*/
|
||
|
|
function deferral_wrap(function_) {
|
||
|
|
return (deferral_make((input, convey) => convey(function_(input))));
|
||
|
|
}
|
||
|
|
call.deferral_wrap = deferral_wrap;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function deferral_id() {
|
||
|
|
return (deferral_make((input, convey) => convey(input)));
|
||
|
|
}
|
||
|
|
call.deferral_id = deferral_id;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function deferral_const(value) {
|
||
|
|
return (deferral_make((input, convey) => convey(value)));
|
||
|
|
}
|
||
|
|
call.deferral_const = deferral_const;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function deferral_delay(output, delay) {
|
||
|
|
return (deferral_make((input, convey) => {
|
||
|
|
setTimeout(() => convey(output), delay);
|
||
|
|
}));
|
||
|
|
}
|
||
|
|
call.deferral_delay = deferral_delay;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
* @desc connects two deferrals to form a new one; the output of the first is taken as input for the second
|
||
|
|
* (similar to "Promise.then" when passing a function which returns a new promise)
|
||
|
|
* @param {type_deferral<type_value1>} first a simple deferral
|
||
|
|
* @param {(value1 : type_value1)=>type_deferral<type_value2>} second a function depending from a value returning a deferral
|
||
|
|
*/
|
||
|
|
function deferral_compose_serial(first, second) {
|
||
|
|
return {
|
||
|
|
"representation": ((input) => first.representation(input).then((between) => second.representation(between)))
|
||
|
|
};
|
||
|
|
}
|
||
|
|
call.deferral_compose_serial = deferral_compose_serial;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function deferral_compose_parallel({ "left": deferral_left, "right": deferral_right, }) {
|
||
|
|
return (deferral_make((input, convey) => {
|
||
|
|
let object = {
|
||
|
|
"left": lib_plankton.pod.make_empty(),
|
||
|
|
"right": lib_plankton.pod.make_empty(),
|
||
|
|
};
|
||
|
|
let finish = function () {
|
||
|
|
if (lib_plankton.pod.is_filled(object.left)
|
||
|
|
&&
|
||
|
|
lib_plankton.pod.is_filled(object.right)) {
|
||
|
|
let result = {
|
||
|
|
"left": lib_plankton.pod.cull(object.left),
|
||
|
|
"right": lib_plankton.pod.cull(object.right),
|
||
|
|
};
|
||
|
|
convey(result);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
// do nothing
|
||
|
|
}
|
||
|
|
};
|
||
|
|
deferral_use(deferral_left, input, output_left => {
|
||
|
|
object.left = lib_plankton.pod.make_filled(output_left);
|
||
|
|
finish();
|
||
|
|
});
|
||
|
|
deferral_use(deferral_right, input, output_right => {
|
||
|
|
object.right = lib_plankton.pod.make_filled(output_right);
|
||
|
|
finish();
|
||
|
|
});
|
||
|
|
}));
|
||
|
|
}
|
||
|
|
call.deferral_compose_parallel = deferral_compose_parallel;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
* @desc repeatedly applied serial composition
|
||
|
|
*/
|
||
|
|
function deferral_chain(members) {
|
||
|
|
return (members.reduce(
|
||
|
|
// (result, current) => deferral_compose_serial<type_value, type_value, type_value>(result, current),
|
||
|
|
deferral_compose_serial, deferral_id()));
|
||
|
|
}
|
||
|
|
call.deferral_chain = deferral_chain;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
/*
|
||
|
|
export function deferral_bunch<type_input, type_output>(
|
||
|
|
members : {[name : string] : type_deferral<type_input, type_output>}
|
||
|
|
) : type_deferral<type_input, {[name : string] : type_output}> {
|
||
|
|
|
||
|
|
}
|
||
|
|
*/
|
||
|
|
})(call = lib_plankton.call || (lib_plankton.call = {}));
|
||
|
|
})(lib_plankton || (lib_plankton = {}));
|
||
|
|
/*
|
||
|
|
This file is part of »bacterio-plankton:call«.
|
||
|
|
|
||
|
|
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||
|
|
<info@greenscale.de>
|
||
|
|
|
||
|
|
»bacterio-plankton:call« is free software: you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU Lesser General Public License as published by
|
||
|
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
»bacterio-plankton:call« is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU Lesser General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU Lesser General Public License
|
||
|
|
along with »bacterio-plankton:call«. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
var lib_plankton;
|
||
|
|
(function (lib_plankton) {
|
||
|
|
var call;
|
||
|
|
(function (call) {
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
class class_deferral {
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
constructor(subject) {
|
||
|
|
this.subject = subject;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
static _cram(subject) {
|
||
|
|
return (new class_deferral(subject));
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
static _tear(instance) {
|
||
|
|
return instance.subject;
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
static make(handler) {
|
||
|
|
return (class_deferral._cram(call.deferral_make(handler)));
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
use(input, procedure) {
|
||
|
|
return (call.deferral_use(class_deferral._tear(this), input, procedure));
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
compose_serial(second) {
|
||
|
|
return (class_deferral._cram(call.deferral_compose_serial(class_deferral._tear(this), class_deferral._tear(second))));
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
static chain(members) {
|
||
|
|
return (class_deferral._cram(call.deferral_chain(members.map(member => class_deferral._tear(member)))));
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
static wrap(function_) {
|
||
|
|
return (class_deferral._cram(call.deferral_wrap(function_)));
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
static const_(value) {
|
||
|
|
return (class_deferral._cram(call.deferral_const(value)));
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
static delay(output, delay) {
|
||
|
|
return (class_deferral._cram(call.deferral_delay(output, delay)));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
call.class_deferral = class_deferral;
|
||
|
|
})(call = lib_plankton.call || (lib_plankton.call = {}));
|
||
|
|
})(lib_plankton || (lib_plankton = {}));
|
||
|
|
/*
|
||
|
|
This file is part of »bacterio-plankton:call«.
|
||
|
|
|
||
|
|
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||
|
|
<info@greenscale.de>
|
||
|
|
|
||
|
|
»bacterio-plankton:call« is free software: you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU Lesser General Public License as published by
|
||
|
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
»bacterio-plankton:call« is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU Lesser General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU Lesser General Public License
|
||
|
|
along with »bacterio-plankton:call«. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
var lib_plankton;
|
||
|
|
(function (lib_plankton) {
|
||
|
|
var call;
|
||
|
|
(function (call) {
|
||
|
|
/**
|
||
|
|
* converts the "arguments"-map into an array
|
||
|
|
*
|
||
|
|
* @param {Object} args
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function args2list(args) {
|
||
|
|
return Object.keys(args).map(key => args[key]);
|
||
|
|
}
|
||
|
|
call.args2list = args2list;
|
||
|
|
/**
|
||
|
|
* just the empty function; useful for some callbacks etc.
|
||
|
|
*
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function nothing() {
|
||
|
|
}
|
||
|
|
call.nothing = nothing;
|
||
|
|
/**
|
||
|
|
* just the identity; useful for some callbacks etc.; defined as function instead of const for using type parameters
|
||
|
|
*
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function id(x) {
|
||
|
|
return x;
|
||
|
|
}
|
||
|
|
call.id = id;
|
||
|
|
/**
|
||
|
|
* just the identity; useful for some callbacks etc.
|
||
|
|
*
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function const_(x) {
|
||
|
|
return (y => x);
|
||
|
|
}
|
||
|
|
call.const_ = const_;
|
||
|
|
/**
|
||
|
|
* composes two functions (i.e. returns a function that return the result of the successive execution of both input-functions)
|
||
|
|
*
|
||
|
|
* @param {function} function_f
|
||
|
|
* @param {function} function_g
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function compose(function_f, function_g) {
|
||
|
|
return (function (x) {
|
||
|
|
// return function_g(function_f(x));
|
||
|
|
return function_g(function_f.apply(function_f, args2list(arguments)));
|
||
|
|
});
|
||
|
|
}
|
||
|
|
call.compose = compose;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function curryfy_real(f, n) {
|
||
|
|
switch (n) {
|
||
|
|
case 0: {
|
||
|
|
throw (new Error("[curryfy] impossible"));
|
||
|
|
// break;
|
||
|
|
}
|
||
|
|
case 1: {
|
||
|
|
return f;
|
||
|
|
// break;
|
||
|
|
}
|
||
|
|
default: {
|
||
|
|
return (function (x) {
|
||
|
|
return (curryfy_real(function () { return f.apply(f, [x].concat(args2list(arguments))); }, n - 1));
|
||
|
|
});
|
||
|
|
// break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* transforms a function with sequential input into a function with leveled input; example: add(2,3) = curryfy(add)(2)(3)
|
||
|
|
*
|
||
|
|
* @param {function} f
|
||
|
|
* @return {function} the currified version of the in put function
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function curryfy(f) {
|
||
|
|
return curryfy_real(f, f.length);
|
||
|
|
}
|
||
|
|
call.curryfy = curryfy;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function convey(value, functions) {
|
||
|
|
let result = value;
|
||
|
|
functions.forEach(function_ => {
|
||
|
|
result = function_(result);
|
||
|
|
});
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
call.convey = convey;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function timeout(procedure, delay) {
|
||
|
|
return (
|
||
|
|
/*window.*/ setTimeout(procedure, delay));
|
||
|
|
}
|
||
|
|
call.timeout = timeout;
|
||
|
|
/**
|
||
|
|
* a definition for a value being "defined"
|
||
|
|
*
|
||
|
|
* @author neuc
|
||
|
|
*/
|
||
|
|
function is_def(obj, options = {}) {
|
||
|
|
options = Object.assign({
|
||
|
|
"null_is_valid": false,
|
||
|
|
}, options);
|
||
|
|
return (!((typeof (obj) === "undefined")
|
||
|
|
||
|
||
|
|
(!options.null_is_valid && (obj === null))));
|
||
|
|
}
|
||
|
|
call.is_def = is_def;
|
||
|
|
/**
|
||
|
|
* returns the value if set and, when a type is specified, if the type is correct, if not return default_value
|
||
|
|
*
|
||
|
|
* @author neuc
|
||
|
|
*/
|
||
|
|
function def_val(value, default_value, options = {}) {
|
||
|
|
options = Object.assign({
|
||
|
|
"type": null,
|
||
|
|
"null_is_valid": false,
|
||
|
|
}, options);
|
||
|
|
if (is_def(value, { "null_is_valid": options.null_is_valid })
|
||
|
|
&&
|
||
|
|
(is_def(options.type)
|
||
|
|
? ((typeof (value) === options.type)
|
||
|
|
||
|
||
|
|
((value === null)
|
||
|
|
&&
|
||
|
|
options.null_is_valid))
|
||
|
|
: true)) {
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
return default_value;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
call.def_val = def_val;
|
||
|
|
;
|
||
|
|
/**
|
||
|
|
* provides the call for an attribute of a class as a regular function; useful for processing lists of objects
|
||
|
|
*
|
||
|
|
* @param {string} name the name of the attribute
|
||
|
|
* @return {function}
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function attribute(name) {
|
||
|
|
return (object => object[name]);
|
||
|
|
}
|
||
|
|
call.attribute = attribute;
|
||
|
|
/**
|
||
|
|
* provides a method of a class as a regular function; useful for processing lists of objects
|
||
|
|
*
|
||
|
|
* @param {string} name the name of the method
|
||
|
|
* @return {function}
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function method(name) {
|
||
|
|
return (function (object) { return object[name].apply(object, args2list(arguments).slice(1)); });
|
||
|
|
}
|
||
|
|
call.method = method;
|
||
|
|
/**
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function distinguish(coproduct, handlers, options = {}) {
|
||
|
|
options = Object.assign({
|
||
|
|
"fallback": null,
|
||
|
|
}, options);
|
||
|
|
if (coproduct.kind in handlers) {
|
||
|
|
const handler = handlers[coproduct.kind];
|
||
|
|
return handler(coproduct.data);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
const message = ("unhandled kind '" + coproduct.kind + "'");
|
||
|
|
if (options.fallback !== null) {
|
||
|
|
console.warn(message);
|
||
|
|
return options.fallback(coproduct);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
throw (new Error(message));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
call.distinguish = distinguish;
|
||
|
|
/**
|
||
|
|
* Promise version of "setTimeout"
|
||
|
|
*
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function defer(seconds, action) {
|
||
|
|
return (new Promise((resolve, reject) => {
|
||
|
|
setTimeout(() => resolve(action()), Math.floor(seconds * 1000));
|
||
|
|
}));
|
||
|
|
}
|
||
|
|
call.defer = defer;
|
||
|
|
/**
|
||
|
|
* rate limiting algorithm, based on the idea of mana (magic power) in video games:
|
||
|
|
* - an actor has a fixed mana capacity, i.e. the maximum amount of available power
|
||
|
|
* - an actor has a fixed rate of mana regeneration, i.e. how fast the power is filled up (linear growth)
|
||
|
|
* - an action has a defined mana heft, i.e. how much power is required and deducted in order to execute it
|
||
|
|
* - mana states are represented by snapshots, i.e. the amount of power at a certain point in time
|
||
|
|
*
|
||
|
|
* @author fenris
|
||
|
|
*/
|
||
|
|
function rate_limit_check(setup, heft) {
|
||
|
|
return __awaiter(this, void 0, void 0, function* () {
|
||
|
|
if (heft > setup.capacity) {
|
||
|
|
return Promise.resolve({
|
||
|
|
"granted": false,
|
||
|
|
"seconds": null,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
// get current value
|
||
|
|
const current_timestamp = (Date.now() / 1000);
|
||
|
|
const old_snapshot_raw = (yield setup.get_snapshot());
|
||
|
|
const old_snapshot = (old_snapshot_raw !== null && old_snapshot_raw !== void 0 ? old_snapshot_raw : { "timestamp": current_timestamp, "value": setup.capacity });
|
||
|
|
const seconds_passed = (current_timestamp - old_snapshot.timestamp);
|
||
|
|
const current_value = Math.min(setup.capacity, (old_snapshot.value
|
||
|
|
+
|
||
|
|
(setup.regeneration_rate
|
||
|
|
*
|
||
|
|
seconds_passed)));
|
||
|
|
// analyze
|
||
|
|
if (current_value < heft) {
|
||
|
|
// too less
|
||
|
|
const seconds_needed = ((setup.regeneration_rate <= 0)
|
||
|
|
? null
|
||
|
|
: ((heft - old_snapshot.value) / setup.regeneration_rate));
|
||
|
|
return Promise.resolve({
|
||
|
|
"granted": false,
|
||
|
|
"seconds": ((seconds_needed === null) ? null : (seconds_needed - seconds_passed)),
|
||
|
|
});
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
// enough -> update snapshot
|
||
|
|
const new_value = (current_value - heft);
|
||
|
|
// set_snapshot
|
||
|
|
if (old_snapshot_raw === null) {
|
||
|
|
yield setup.set_snapshot({ "timestamp": current_timestamp, "value": new_value });
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
yield setup.update_snapshot(current_timestamp, (new_value - old_snapshot.value));
|
||
|
|
}
|
||
|
|
return Promise.resolve({
|
||
|
|
"granted": true,
|
||
|
|
"seconds": 0,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
call.rate_limit_check = rate_limit_check;
|
||
|
|
})(call = lib_plankton.call || (lib_plankton.call = {}));
|
||
|
|
})(lib_plankton || (lib_plankton = {}));
|