From 4dbb7474e7c4b91616a482f1019f0e271efd7f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fra=C3=9F?= Date: Sun, 18 Jun 2023 23:29:57 +0200 Subject: [PATCH] [int] --- .gitignore | 1 + lib/plankton/plankton.d.ts | 1775 +++++++++ lib/plankton/plankton.js | 5427 +++++++++++++++++++++++++++ source/localization/de.json | 1 + source/localization/en.json | 1 + source/logic/channels/_type.ts | 12 + source/logic/checks/_type.ts | 12 + source/logic/condition.ts | 13 + source/logic/helpers/json_schema.ts | 47 + source/logic/main.ts | 237 ++ source/logic/order.ts | 546 +++ source/misc/head.js | 1 + tools/build | 141 +- tools/heimdall.prj.json | 68 + tools/makefile | 14 + tools/postprocess | 7 + tools/update-plankton | 23 + 17 files changed, 8194 insertions(+), 132 deletions(-) create mode 100644 lib/plankton/plankton.d.ts create mode 100644 lib/plankton/plankton.js create mode 100644 source/logic/channels/_type.ts create mode 100644 source/logic/checks/_type.ts create mode 100644 source/logic/condition.ts create mode 100644 source/logic/helpers/json_schema.ts create mode 100644 source/logic/main.ts create mode 100644 source/logic/order.ts create mode 100644 source/misc/head.js create mode 100644 tools/heimdall.prj.json create mode 100644 tools/makefile create mode 100755 tools/postprocess create mode 100755 tools/update-plankton diff --git a/.gitignore b/.gitignore index 97412a1..64b5221 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .geany source/__pycache__/ +temp/ build/ diff --git a/lib/plankton/plankton.d.ts b/lib/plankton/plankton.d.ts new file mode 100644 index 0000000..9d39880 --- /dev/null +++ b/lib/plankton/plankton.d.ts @@ -0,0 +1,1775 @@ +/** + * @author fenris + */ +type int = number; +/** + * @author fenris + */ +type float = number; +/** + * @author fenris + */ +type type_time = { + hours: int; + minutes: int; + seconds: int; +}; +declare var process: any; +declare var require: any; +declare class Buffer { + constructor(x: string, modifier?: string); + toString(modifier?: string): string; +} +declare namespace lib_plankton.base { + /** + * @author fenris + */ + function environment(): string; +} +/** + * @author fenris + */ +type type_pseudopointer = { + value: type_value; +}; +/** + * @author fenris + */ +declare function pseudopointer_null(): type_pseudopointer; +/** + * @author fenris + */ +declare function pseudopointer_make(value: type_value): type_pseudopointer; +/** + * @author fenris + */ +declare function pseudopointer_isset(pseudopointer: type_pseudopointer): boolean; +/** + * @author fenris + */ +declare function pseudopointer_read(pseudopointer: type_pseudopointer): type_value; +/** + * @author fenris + */ +declare function pseudopointer_write(pseudopointer: type_pseudopointer, value: type_value): void; +/** + * @author fenris + */ +declare var instance_verbosity: int; +/** + * @desc the ability to check for equality with another element of the same domain + * @author fenris + */ +interface interface_collatable { + /** + * @author fenris + */ + _collate(value: type_value): boolean; +} +/** + * @author fenris + */ +declare function instance_collate(value1: (type_value & { + _collate?: ((value: type_value) => boolean); +}), value2: type_value): boolean; +/** + * @desc the ability to compare with another element of the same domain for determining if the first is "smaller than or equal to" the latter + * @author fenris + */ +interface interface_comparable { + /** + * @author fenris + */ + _compare(value: type_value): boolean; +} +/** + * @author fenris + */ +declare function instance_compare(value1: (type_value & { + _compare: ((value: type_value) => boolean); +}), value2: type_value): boolean; +/** + * @desc the ability to create an exact copy + * @author fenris + */ +interface interface_cloneable { + /** + * @author fenris + */ + _clone(): type_value; +} +/** + * @author fenris + */ +declare function instance_clone(value: (type_value & { + _clone?: (() => type_value); +})): type_value; +/** + * @author fenris + */ +interface interface_hashable { + /** + * @author fenris + */ + _hash(): string; +} +/** + * @desc the ability to generate a string out of the element, which identifies it to a high degree + * @author fenris + */ +declare function instance_hash(value: (type_value & { + _hash?: (() => string); +})): string; +/** + * @author fenris + */ +interface interface_showable { + /** + * @author fenris + */ + _show(): string; +} +/** + * @desc the ability to map the element to a textual representation (most likely not injective) + * @author fenris + */ +declare function instance_show(value: (type_value & { + _show?: (() => string); +})): string; +/** + * @author frac + */ +interface interface_decorator { + /** + * @author frac + */ + core: type_core; +} +/** + * @author frac + */ +declare class class_observer { + /** + * @author frac + */ + protected counter: int; + /** + * @author frac + */ + protected actions: { + [id: string]: (information: Object) => void; + }; + /** + * @author frac + */ + protected buffer: Array; + /** + * @author frac + */ + constructor(); + /** + * @author frac + */ + empty(): boolean; + /** + * @author frac + */ + flush(): void; + /** + * @author frac + */ + set(id: string, action: (information: Object) => void): void; + /** + * @author frac + */ + del(id: string): void; + /** + * @author frac + */ + add(action: (information: Object) => void): void; + /** + * @author frac + */ + notify(information?: Object, delayed?: boolean): void; + /** + * @author frac + */ + rollout(): void; +} +/** + * @author frac + */ +/** + * @author frac + */ +declare module lib_maybe { + /** + * @author fenris + */ + type type_maybe = { + kind: string; + parameters: Object; + }; + /** + * @author fenris + */ + function make_nothing(): type_maybe; + /** + * @author fenris + */ + function make_just(value: type_value): type_maybe; + /** + * @author fenris + */ + function is_nothing(maybe: type_maybe): boolean; + /** + * @author fenris + */ + function is_just(maybe: type_maybe): boolean; + /** + * @author fenris + */ + function cull(maybe: type_maybe): type_value; + /** + * @author fenris + */ + function propagate(maybe: type_maybe, function_: (value: type_value) => type_maybe): type_maybe; +} +/** + * @author fenris + */ +declare class class_maybe implements interface_showable { + /** + * @desc whether the wrapper is nothing + * @author fenris + */ + is_nothing(): boolean; + /** + * @desc whether the wrapper is just + * @author fenris + */ + is_just(): boolean; + /** + * @desc return the value, stored in the maybe-wrapper + * @author fenris + */ + cull(): type_value; + /** + * @author fenris + */ + toString(): string; + /** + * @author fenris + */ + distinguish(action_just: (value?: type_value) => void, action_nothing?: (reason?: string) => void): void; + /** + * @author fenris + */ + propagate(action: (value: type_value) => class_maybe): class_maybe; + /** + * @desc [implementation] + * @author fenris + */ + _show(): string; +} +/** + * @author fenris + */ +declare class class_nothing extends class_maybe { + /** + * @author fenris + */ + private reason; + /** + * @author fenris + */ + constructor(reason?: string); + /** + * @author fenris + */ + is_nothing(): boolean; + /** + * @author fenris + */ + is_just(): boolean; + /** + * @author fenris + */ + cull(): type_value; + /** + * @author fenris + */ + toString(): string; + /** + * @author fenris + */ + reason_get(): string; + /** + * @author fenris + */ + distinguish(action_just: (value?: type_value) => void, action_nothing?: (reason?: string) => void): void; + /** + * @author fenris + */ + propagate(action: (value: type_value) => class_maybe): class_maybe; +} +/** + * @author fenris + */ +declare class class_just extends class_maybe { + /** + * @author fenris + */ + private value; + /** + * @author fenris + */ + constructor(value: type_value); + /** + * @author fenris + */ + is_nothing(): boolean; + /** + * @author fenris + */ + is_just(): boolean; + /** + * @author fenris + */ + cull(): type_value; + /** + * @author fenris + */ + toString(): string; + /** + * @author fenris + */ + distinguish(action_just: (value?: type_value) => void, action_nothing?: (reason?: string) => void): void; + /** + * @author fenris + */ + propagate(action: (value: type_value) => class_maybe): class_maybe; +} +/** + * @author frac + */ +declare class class_error extends Error { + /** + * @author frac + */ + protected suberrors: Array; + /** + * @author frac + */ + protected mess: string; + /** + * @author frac + */ + constructor(message: string, suberrors?: Array); + /** + * @override + * @author frac + */ + toString(): string; +} +declare namespace lib_plankton.base { + /** + * returns the current UNIX timestamp + * + * @author fenris + */ + function get_current_timestamp(rounded?: boolean): int; + /** + */ + function object_merge(core: Record, mantle: Record): Record; +} +declare namespace lib_plankton.log { + /** + */ + enum enum_level { + debug = 0, + info = 1, + notice = 2, + warning = 3, + error = 4 + } + /** + */ + function level_order(level1: enum_level, level2: enum_level): boolean; + /** + */ + function level_show(level: enum_level): string; + /** + */ + type type_entry = { + level: enum_level; + incident: string; + details: Record; + }; +} +/** + * @deprecated + * @todo remove + */ +declare namespace lib_plankton.log { + function level_push(level: int): void; + function level_pop(): void; + function indent_push(indent: int): void; + function indent_pop(): void; + function indent_inc(): void; + function indent_dec(): void; + /** + * @author fenris + */ + function write({ "message": message, "type": type, "prefix": prefix, "level": level, "indent": indent, }: { + message?: string; + type?: string; + prefix?: string; + level?: int; + indent?: int; + }): void; +} +declare namespace lib_plankton.log { + /** + */ + abstract class class_channel { + /** + */ + abstract add(entry: type_entry): void; + } +} +declare namespace lib_plankton.log { + /** + * output for writing log entries to stdout + */ + class class_channel_stdout extends class_channel { + /** + */ + add(entry: type_entry): void; + } +} +declare namespace lib_plankton.log { + /** + */ + class class_channel_file extends class_channel { + /** + * the path of the log file + */ + private path; + /** + * [constructor] + */ + constructor(path: string); + /** + */ + add(entry: type_entry): void; + } +} +declare namespace lib_plankton.log { + /** + * output for desktop notifications via "libnotify" + */ + class class_channel_notify extends class_channel { + /** + */ + add(entry: type_entry): void; + } +} +declare namespace lib_plankton.log { + /** + * decorator for filtering out log entries below a certain level threshold + */ + class class_channel_minlevel extends class_channel { + /** + */ + private core; + /** + */ + private threshold; + /** + */ + constructor(core: class_channel, threshold: enum_level); + /** + */ + add(entry: type_entry): void; + } +} +declare namespace lib_plankton.log { + /** + */ + function channel_make(description: { + kind: string; + data?: { + [key: string]: any; + }; + }): class_channel; + /** + */ + type type_configuration = Array; + /** + */ + function conf_default(): type_configuration; +} +declare namespace lib_plankton.log { + /** + * pushes a new configuration on the stack and activates it + */ + function conf_push(channels: type_configuration): void; + /** + * pops the current active configuration from the stack + */ + function conf_pop(): void; + /** + * consumes a log entry, i.e. sends it to the currently active outputs + */ + function add(entry: type_entry): void; + /** + */ + function debug(incident: string, details?: Record): void; + /** + */ + function info(incident: string, details?: Record): void; + /** + */ + function notice(incident: string, details?: Record): void; + /** + */ + function warning(incident: string, details?: Record): void; + /** + */ + function error(incident: string, details?: Record): void; +} +declare var plain_text_to_html: (text: string) => string; +/** + * @desc makes a valid + */ +declare var format_sentence: (str: string, rtl?: boolean, caseSense?: boolean) => string; +declare var fill_string_template: (template_string: string, object: any, fabric: Function, delimiter: string, default_string: string, sloppy: boolean) => string; +declare var make_string_template: (_template: string, _fabrics?: Object) => (object: { + [key: string]: string; +}) => string; +declare var make_eml_header: (object: { + [key: string]: string; +}) => string; +declare var make_eml_body: Object; +declare namespace lib_plankton.string { + /** + * @author neuc,frac + */ + function empty(str: string): boolean; + /** + * @desc returns a unique string + * @param {string} prefix an optional prefix for the generated string + * @return {string} + * @author fenris + */ + function generate(prefix?: string): string; + /** + * @desc splits a string, but returns an empty list, if the string is empty + * @param {string} chain + * @param {string} separator + * @return {Array} + * @author fenris + */ + function split(chain: string, separator?: string): Array; + /** + * @author neu3no + */ + function explode(str: string, needle: string, max: int): Array; + /** + * @desc concats a given word with itself n times + * @param {string} word + * @param {int} + * @return {string} + * @author fenris + */ + function repeat(word: string, count: int): string; + /** + * @desc lengthens a string by repeatedly appending or prepending another string + * @param {string} word the string to pad + * @param {int} length the length, which the result shall have + * @param {string} symbol the string, which will be added (multiple times) + * @param {boolean} [prepend]; whether to prepend (~true) or append (~false); default: false + * @return {string} the padded string + * @author fenris + */ + function pad(word: string, length: int, symbol?: string, mode?: string): string; + /** + * @desc checks if a given string conttains a certain substring + * @param {string} string + * @param {string} part + * @return {boolean} + * @author fenris + */ + function contains(chain: string, part: string): boolean; + /** + * @desc checks if a given string starts with a certain substring + * @param {string} string + * @param {string} part + * @return {boolean} + * @author fenris + */ + function startsWith(chain: string, part: string): boolean; + /** + * @desc checks if a given string ends with a certain substring + * @param {string} string + * @param {string} part + * @return {boolean} + * @author fenris + */ + function endsWith(chain: string, part: string): boolean; + /** + * @desc count the occourrences of a string in a string + * @param string haystack_string the string wich should be examined + * @param string needle_string the string which should be counted + * @author neuc + */ + function count_occourrences(haystack_string: string, needle_string: string, check_escape: boolean): int; + /** + * @author fenris + */ + function replace(str: string, replacements: Array<{ + from: string; + to: string; + }>, options?: {}): string; + /** + * @desc replaces occurences of "${name}" in a string by the corresponding values of an argument object + * @author fenris + */ + function coin(str: string, args: { + [id: string]: string; + }, options?: { + legacy?: boolean; + open?: string; + close?: string; + }): string; + /** + * @author fenris + */ + function cut(str: string, length: int, delimiter?: string): string; +} +/** + * @deprecated + */ +declare namespace lib_string { + const empty: typeof lib_plankton.string.empty; + const generate: typeof lib_plankton.string.generate; + const split: typeof lib_plankton.string.split; + const explode: typeof lib_plankton.string.repeat; + const repeat: typeof lib_plankton.string.repeat; + const pad: typeof lib_plankton.string.pad; + const contains: typeof lib_plankton.string.contains; + const startsWith: typeof lib_plankton.string.startsWith; + const endsWith: typeof lib_plankton.string.endsWith; + const count_occourrences: typeof lib_plankton.string.count_occourrences; + const coin: typeof lib_plankton.string.coin; + const stance: typeof lib_plankton.string.coin; + const cut: typeof lib_plankton.string.cut; +} +declare namespace lib_plankton.string { + /** + * an implementation of c sprintf + * @param {string} string format string + * @param {array} args arguments which should be filled into + * @returns {string} + */ + var sprintf: (input: string, args?: Array, original?: any) => string; + /** + * an implementation of c printf + * @param {string} string format string + * @param {array} args arguments which should be filled into + * @returns {string} + */ + function printf(format: any, args: any): void; +} +declare var sprintf: (input: string, args?: Array, original?: any) => string; +declare var printf: typeof lib_plankton.string.printf; +declare var eml_log: any; +declare var track_exports: any; +declare var make_logger: (prefix: any, current_loglevel: any) => (obj: any, lvl: any) => void; +declare namespace lib_plankton.code { + /** + * @author fenris + */ + interface interface_code { + /** + * @author fenris + */ + encode(x: type_from): type_to; + /** + * @author fenris + */ + decode(x: type_to): type_from; + } +} +declare namespace lib_plankton.code { + /** + * @author fenris + */ + type type_code = { + /** + * @author fenris + */ + encode: (x: type_from) => type_to; + /** + * @author fenris + */ + decode: (x: type_to) => type_from; + }; +} +declare namespace lib_plankton.code { + /** + * @author fenris + */ + function inverse_encode(decode: (to: type_to) => type_from, to: type_to): type_from; + /** + * @author fenris + */ + function inverse_decode(encode: (from: type_from) => type_to, from: type_from): type_to; +} +declare namespace lib_plankton.code { + /** + * @author fenris + */ + class class_code_inverse implements interface_code { + /** + * @author fenris + */ + protected subject: interface_code; + /** + * @author fenris + */ + constructor(subject: interface_code); + /** + * @implementation + * @author fenris + */ + encode(to: type_to): type_from; + /** + * @implementation + * @author fenris + */ + decode(from: type_from): type_to; + } +} +declare namespace lib_plankton.code { + /** + * @author fenris + */ + function pair_encode(encode_first: (from: type_from) => type_between, encode_second: (between: type_between) => type_to, from: type_from): type_to; + /** + * @author fenris + */ + function pair_decode(decode_first: (between: type_between) => type_from, decode_second: (to: type_to) => type_between, to: type_to): type_from; +} +declare namespace lib_plankton.code { + /** + * @author fenris + */ + class class_code_pair implements interface_code { + /** + * @author fenris + */ + protected first: interface_code; + /** + * @author fenris + */ + protected second: interface_code; + /** + * @author fenris + */ + constructor(first: interface_code, second: interface_code); + /** + * @implementation + * @author fenris + */ + encode(from: type_from): type_to; + /** + * @implementation + * @author fenris + */ + decode(to: type_to): type_from; + } +} +declare namespace lib_plankton.code { + /** + * @author fenris + */ + function chain_encode(encode_links: Array<(from: any) => any>, from: any): any; + /** + * @author fenris + */ + function chain_decode(decode_links: Array<(to: any) => any>, to: any): any; +} +declare namespace lib_plankton.code { + /** + * @author fenris + */ + class class_code_chain implements interface_code { + /** + * @author fenris + */ + protected links: Array>; + /** + * @author fenris + */ + constructor(links: Array>); + /** + * @implementation + * @author fenris + */ + encode(from: any): any; + /** + * @implementation + * @author fenris + */ + decode(to: any): any; + } +} +declare namespace lib_plankton.code { + /** + * @author Christian Fraß + */ + type type_flatten_from = Array<{ + [name: string]: any; + }>; + /** + * @author Christian Fraß + */ + type type_flatten_to = { + keys: Array; + data: Array>; + }; + /** + * @author Christian Fraß + */ + function flatten_encode(from: type_flatten_from, keys?: Array): type_flatten_to; + /** + * @author Christian Fraß + */ + function flatten_decode(to: type_flatten_to): type_flatten_from; +} +declare namespace lib_plankton.code { + /** + * @author fenris + */ + class class_code_flatten implements interface_code { + /** + * @author fenris + */ + constructor(); + /** + * @implementation + * @author fenris + */ + encode(x: type_flatten_from): type_flatten_to; + /** + * @implementation + * @author fenris + */ + decode(x: type_flatten_to): type_flatten_from; + } +} +declare namespace lib_plankton.json { + /** + * @author fenris + */ + function encode(x: any, formatted?: boolean): string; + /** + * @author fenris + */ + function decode(x: string): any; +} +declare namespace lib_plankton.json { + /** + * @author fenris + */ + class class_json implements lib_plankton.code.interface_code { + /** + * @author fenris + */ + constructor(); + /** + * @implementation + * @author fenris + */ + encode(x: any): string; + /** + * @implementation + * @author fenris + */ + decode(x: string): any; + } +} +declare namespace lib_plankton.file { + /** + * @author fenris + */ + function read(path: string): Promise; + /** + * @author fenris + */ + function read_buffer(path: string): Promise; + /** + * @author fenris + */ + function read_stdin(): Promise; + /** + * @author fenris + */ + function write(path: string, content: string, options?: { + encoding?: string; + }): Promise; + /** + * @author fenris + */ + function write_buffer(path: string, content: Buffer, options?: {}): Promise; +} +declare namespace lib_plankton.object { + /** + * @author fenris + */ + function fetch(object: Object, fieldname: string, fallback?: type_value, escalation?: int): type_value; + /** + * @author fenris + */ + function map(object_from: { + [key: string]: type_from; + }, transformator: (value_from: type_from, key?: string) => type_to): { + [key: string]: type_to; + }; + /** + * @desc gibt ein Objekt mit bestimmten Einträgen des Eingabe-Objekts zurück + * @author fenris + */ + function filter(object_from: { + [key: string]: type_value; + }, predicate: (value_from: type_value, key?: string) => boolean): { + [key: string]: type_value; + }; + /** + * @desc wandelt ein Array mit Einträgen der Form {key,value} in ein entsprechendes Objekt um + * @author fenris + */ + function from_array(array: Array<{ + key: string; + value: type_value; + }>): { + [key: string]: type_value; + }; + /** + * @desc wandelt ein Objekt in ein entsprechendes Array mit Einträgen der Form {key,value} um + * @author fenris + */ + function to_array(object: { + [key: string]: type_value; + }): Array<{ + key: string; + value: type_value; + }>; + /** + * @desc gibt eine Liste von Schlüsseln eines Objekts zurück + * @author fenris + */ + function keys(object: { + [key: string]: any; + }): Array; + /** + * @desc gibt eine Liste von Werten eines Objekts zurück + * @author fenris + */ + function values(object: { + [key: string]: type_value; + }): Array; + /** + * @desc liest ein Baum-artiges Objekt an einer bestimmten Stelle aus + * @author fenris + */ + function path_read(object: Object, path: string, fallback?: type_value, escalation?: int): type_value; + /** + * @desc schreibt einen Wert an eine bestimmte Stelle in einem Baum-artigen Objekt + * @author fenris + */ + function path_write(object: Object, path: string, value: type_value, construct?: boolean): void; + /** + * @desc prüft ob ein Objekt einem bestimmten Muster entspricht + * @param {Object} object das zu prüfende Objekt + * @param {Object} pattern das einzuhaltende Muster + * @param {Function} connlate eine Funktion zum Feststellen der Gleichheit von Einzelwerten + * @author fenris + */ + function matches(object: Object, pattern: Object, collate?: typeof instance_collate): boolean; + /** + * @desc erzeugt eine Projektion eines Baum-artigen Objekts in ein Listen-artiges Objekt + * @param {string} [separator] welches Zeichen als Trenner zwischen zwei Pfad-Schritten verwendet werden soll + * @author fenris + */ + function flatten(value: any, separator?: string, key_for_element?: (index: int) => string): Object; + /** + * @author fenris + */ + function clash(x: { + [key: string]: any; + }, y: { + [key: string]: any; + }, { "overwrite": overwrite, "hooks": { "existing": hook_existing, }, }?: { + overwrite?: boolean; + hooks?: { + existing?: (key?: string, value_old?: any, value_new?: any) => void; + }; + }): { + [key: string]: any; + }; + /** + * @author fenris + */ + function patch(core: Object, mantle: Object, deep?: boolean, path?: string): void; + /** + * @author fenris + */ + function patched(core: Object, mantle: Object, deep?: boolean): Object; + /** + * @author fenris + */ + function attached(object: Object, key: string, value: any): Object; + /** + * @author fenris + */ + function copy(object: Object): Object; +} +declare namespace lib_plankton.call { + /** + * @desc hacked class for postfix function application + * @author fenris + */ + class class_valuewrapper { + /** + * @author fenris + */ + protected value: type_value; + /** + * @desc [constructor] + * @author fenris + */ + constructor(value: type_value); + /** + * @desc [accessor] applies a function and returns a new valuewrapper + * @author fenris + */ + pass(function_: (value: type_value) => type_value_): class_valuewrapper; + /** + * @desc [accessor] gives the wrapped value + * @author fenris + */ + extract(): type_value; + } + /** + * @desc shortcut for constructing a valuewrapper-object + * @author fenris + */ + function vw(value: type_value): class_valuewrapper; + /** + * @author fenris + */ + function use(input: type_input, function_: (input: type_input) => type_output): type_output; + /** + * @desc just the identity; useful for some callbacks etc. + * @author fenris + */ + function id(x: type_value): type_value; + /** + * @desc 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: (type_x: any) => type_y, function_g: (type_y: any) => type_z): (value: type_x) => type_z; + /** + * @desc transforms a function with sequential input into a function with leveled input; example: add(2,3) = curryfy(add)(2)(3) + * @param {function} f + * @param {int} n (don't set manually) + * @return {function} the currified version of the in put function + * @author fenris + */ + function curryfy(f: Function, n?: int): Function; +} +declare namespace lib_plankton.call { + /** + * @author fenris + */ + type type_executor = ((resolve: (result?: type_result) => any, reject?: (reason?: type_reason) => void) => void); + /** + * @author fenris + */ + function executor_resolve(result: type_result): type_executor; + /** + * @author fenris + */ + function executor_reject(reason: type_reason): type_executor; + /** + * @author fenris + */ + function executor_transform(executor: type_executor, transform_result: (result_from: type_result_from) => type_result_to, transform_reason: (error_from: type_error_from) => type_error_to): type_executor; + /** + * @author fenris + */ + function executor_transform_default(executor: type_executor, transform_result: (result_from: type_result_from) => type_result_to, wrap_string?: string): type_executor; + /** + * @author fenris + */ + function executor_compose_sequential(first: type_executor, second: (result: type_result_first) => type_executor): type_executor; + /** + * @author fenris + */ + function executor_chain(state: type_state, executors: Array<(state: type_state) => type_executor>): type_executor; + /** + * @author fenris + */ + function executor_first(executors: Array>): type_executor>; + /** + * @author fenris + */ + function executor_condense(executors: Array>): type_executor, Error>; + /** + * @author fenris + * @deprecated use condense + */ + function executor_filter(executors: Array>, predicate: (element: type_element) => boolean): type_executor, Error>; + /** + * @author fenris + * @deprecated use condense + */ + function executor_map(executors: Array>, transformator: (element1: type_element1) => type_element2): type_executor, Error>; + /** + * @author fenris + * @deprecated use condense + */ + function executor_reduce(executors: Array>, initial: type_result, accumulator: (result: type_result, element: type_element) => type_result): type_executor; +} +declare namespace lib_plankton.call { + /** + * @author fenris + */ + type type_promise = Promise; + /** + * @author fenris + */ + function promise_reject(reason: type_reason): type_promise; + /** + * @author fenris + */ + function promise_resolve(result: type_result): type_promise; + /** + * @author fenris + */ + function promise_make(executor: (resolve: (result?: type_result) => void, reject: (reason?: type_reason) => void) => void): type_promise; + /** + * @author fenris + */ + function promise_then_close(promise: type_promise, resolver: (result: type_result) => void, rejector: (reason: type_reason) => void): void; + /** + * @author fenris + */ + function promise_then_append(promise: type_promise, resolver: (result: type_result) => type_promise, rejector?: (reason: type_reason) => type_promise): type_promise; + /** + * @author fenris + */ + function promise_all(promises: Array>): type_promise, type_reason>; + /** + * @author fenris + */ + function promise_chain(promises: Array<(input: type_result) => type_promise>, start?: type_result): type_promise; + /** + * @author fenris + */ + function promise_condense(promises: Array<() => type_promise>): type_promise, type_reason>; + /** + * @author fenris + */ + function promise_group(promises: { + [name: string]: () => type_promise; + }, serial?: boolean): type_promise<{ + [name: string]: any; + }, type_reason>; + /** + * @author fenris + */ + function promise_wrap(promise: type_promise, transformator_result: (reason: type_result_inner) => type_result_outer, transformator_reason?: (reason: type_reason) => type_reason): type_promise; + /** + * @author fenris + */ + function promise_show(label: string): (result: type_result) => type_promise; + /** + * @author fenris + */ + function promise_log(result: type_result): (result: type_result) => type_promise; + /** + * @author fenris + */ + function promise_attach(state: { + [name: string]: any; + }, promise: type_promise, name: string): type_promise<{ + [name: string]: any; + }, type_reason>; + /** + * @author fenris + */ + function promise_delay(promise: type_promise, delay: int): type_promise; + /** + * @author fenris + */ + function promise_to_executor(promise: type_promise): type_executor; +} +declare namespace lib_plankton.call { + /** + * @author fenris + */ + type type_initializer_state = int; + const initializer_state_initial: type_initializer_state; + const initializer_state_waiting: type_initializer_state; + const initializer_state_successful: type_initializer_state; + const initializer_state_failed: type_initializer_state; + /** + * @author fenris + */ + type type_initializer = { + fetcher: () => type_promise; + state?: type_initializer_state; + queue: Array<{ + resolve: (result?: type_result) => void; + reject: (reason?: type_reason) => void; + }>; + result?: type_result; + reason?: type_reason; + }; + /** + * @author fenris + */ + function initializer_make(fetcher: () => type_promise): type_initializer; + /** + * @author fenris + */ + function initializer_reset(subject: type_initializer): void; + /** + * @author fenris + */ + function initializer_state(subject: type_initializer): type_initializer_state; + /** + * @author fenris + */ + function initializer_get(subject: type_initializer): type_promise; +} +declare namespace lib_plankton.call { + /** + * @author fenris + */ + type type_deferral = { + representation: (input: type_input) => Promise; + }; + /** + * @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: type_deferral, input: type_input, procedure: (output: type_output) => void): void; + /** + * @author fenris + * @desc creates a deferral-subject (similar to "new Promise", where "convey" reflects "resolve"/"reject") + */ + function deferral_make(handler: (input: type_input, convey: (output: type_output) => void) => void): type_deferral; + /** + * @author fenris + * @desc wraps a simple function into a deferral (similar to "Promise.resolve"/"Promise.reject") + */ + function deferral_wrap(function_: (input: type_input) => type_output): type_deferral; + /** + * @author fenris + */ + function deferral_id(): type_deferral; + /** + * @author fenris + */ + function deferral_const(value: type_value): type_deferral; + /** + * @author fenris + */ + function deferral_delay(output: type_output, delay: int): type_deferral; + /** + * @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} first a simple deferral + * @param {(value1 : type_value1)=>type_deferral} second a function depending from a value returning a deferral + */ + function deferral_compose_serial(first: type_deferral, second: type_deferral): type_deferral; + /** + * @author fenris + */ + function deferral_compose_parallel({ "left": deferral_left, "right": deferral_right, }: { + left: type_deferral; + right: type_deferral; + }): type_deferral; + /** + * @author fenris + * @desc repeatedly applied serial composition + */ + function deferral_chain(members: Array>): type_deferral; + /** + * @author fenris + */ +} +declare namespace lib_plankton.call { + /** + * @author fenris + */ + class class_deferral { + /** + * @author fenris + */ + private subject; + /** + * @author fenris + */ + private constructor(); + /** + * @author fenris + */ + private static _cram; + /** + * @author fenris + */ + private static _tear; + /** + * @author fenris + */ + static make(handler: (input: type_input, convey: (value: type_output) => void) => void): class_deferral; + /** + * @author fenris + */ + use(input: type_input, procedure: (value: type_output) => void): void; + /** + * @author fenris + */ + compose_serial(second: class_deferral): class_deferral; + /** + * @author fenris + */ + static chain(members: Array>): class_deferral; + /** + * @author fenris + */ + static wrap(function_: (input: type_input) => type_output): class_deferral; + /** + * @author fenris + */ + static const_(value: type_value): class_deferral; + /** + * @author fenris + */ + static delay(output: type_output, delay: int): class_deferral; + } +} +declare namespace lib_plankton.call { + /** + * @author fenris + */ + function timeout(function_: () => void, delay: int): int; + /** + * @desc a definition for a value being "defined" + * @author neuc + */ + function is_def(obj: type_value, null_is_valid?: boolean): boolean; + /** + * @desc 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: any, default_value: any, type?: string, null_is_valid?: boolean): any; + /** + * @desc just the empty function; useful for some callbacks etc. + * @author fenris + */ + function nothing(): void; + /** + * @desc outputs + * @author fenris + */ + /** + * @desc converts the "arguments"-map into an array + * @param {Object} args + * @author fenris + */ + function args2list(args: any): Array; + /** + * @desc provides the call for an attribute of a class as a regular function + * @param {string} name the name of the attribute + * @return {*} + * @author fenris + */ + function attribute(name: string): (object: type_object) => type_attribute; + /** + * @desc provides a method of a class as a regular function + * @param {string} name the name of the method + * @return {function} + * @author fenris + */ + function method(name: string): (object: type_object) => type_output; + /** + * @author fenris + */ + type type_unival = { + kind: string; + data?: any; + }; + /** + * @author fenris + */ + function distinguish(unival: type_unival, handlers: { + [kind: string]: (data?: any) => any; + }, fallback?: (unival?: type_unival) => any): any; + /** + * Promise version of "setTimeout" + * + * @author fenris + */ + function defer(seconds: int, action: (() => type_result)): Promise; + /** + * for rate_limit_check + * + * @author fenris + */ + type type_mana_snapshot = { + timestamp: float; + value: float; + }; + /** + * 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: { + capacity: float; + regeneration_rate: float; + get_snapshot: (() => Promise<(null | type_mana_snapshot)>); + set_snapshot: ((snapshot: type_mana_snapshot) => Promise); + update_snapshot: ((timestamp: float, value_increment: float) => Promise); + }, heft: float): Promise<{ + granted: boolean; + seconds: (null | float); + }>; +} +declare namespace lib_plankton.translate { + /** + * @author fenris + */ + type type_package_meta = { + identifier: string; + name?: string; + }; + /** + * @author fenris + */ + type type_package = { + meta: type_package_meta; + tree: { + [id: string]: string; + }; + }; + /** + * @desc the level of verbosity, specifiying how much output the system shall provide about its actions + * @author fenris + */ + var _verbosity: int; + /** + * @desc moves a language to the top of the order, making it the primary one + * @author fenris + */ + function promote(identifier: string): void; + /** + * @desc adds a package to the sytem + * @author fenris + */ + function add(package_: type_package): void; + /** + * @desc integrates a package to the system, i.e. creates a new one if none existed so far or merges with an existing one + * @author fenris + */ + function feed(package_: type_package): void; + /** + * @desc tries to retrieve a translation for a specific package identifier + * @author fenris + */ + function fetch(identifier: string, path: string, args?: { + [id: string]: string; + }): class_maybe; + /** + * @desc retrieves a string by going through the order and trying to fetch it for the current entry + * @author fenris + */ + function get(path: string, args?: { + [id: string]: string; + }, fallback?: string): string; + /** + * @author fenris + */ + function list(): Array; + /** + * @author fenris + * @todo get rid of this; it's currenly needed only for the cdh-internal lib_completion + */ + function paths(): Array; + /** + * @author fenris + */ + function initialize_promise({ "logprefix": logprefix, "verbosity": verbosity, "packages": packages, "order": order, "autopromote": autopromote, }?: { + logprefix?: string; + verbosity?: int; + packages?: Array; + order?: Array; + autopromote?: boolean; + }): lib_plankton.call.type_promise; + /** + * @author fenris + */ + function initialize_executor(stuff?: any): lib_plankton.call.type_executor; + /** + * @author fenris + */ + function initialize(stuff?: any): lib_plankton.call.type_executor; +} +declare namespace lib_plankton.translate { + /** + * @author fenris + */ + function iso_639_1_to_iso_639_2(iso6391: string): string; + /** + * @author fenris + */ + function stance(str: string): string; +} +declare namespace lib_plankton.args { + /** + */ + enum enum_environment { + cli = "cli", + url = "url" + } + /** + */ + enum enum_kind { + positional = "positional", + volatile = "volatile" + } + /** + */ + enum enum_type { + boolean = "boolean", + integer = "int", + float = "float", + string = "string" + } + /** + */ + enum enum_mode { + replace = "replace", + accumulate = "accumulate" + } +} +declare namespace lib_plankton.args { + /** + * @author fenris + */ + class class_argument { + /** + * @author fenris + */ + protected name: string; + /** + * @author fenris + */ + protected kind: enum_kind; + /** + * @author fenris + */ + protected type: enum_type; + /** + * @author fenris + */ + protected mode: enum_mode; + /** + * @author fenris + */ + protected default_: any; + /** + * @author fenris + */ + protected info: string; + /** + * @author fenris + */ + protected parameters: Object; + /** + * @author fenris + */ + protected hidden: boolean; + /** + * @author fenris + */ + constructor({ "name": name, "type": type, "kind": kind, "mode": mode, "default": default_, "info": info, "parameters": parameters, "hidden": hidden, }: { + name: string; + type?: enum_type; + kind?: enum_kind; + mode?: enum_mode; + default?: any; + info?: string; + parameters?: Object; + hidden?: boolean; + }); + /** + * @author fenris + */ + static positional({ "name": name, "type": type, "mode": mode, "default": default_, "info": info, "hidden": hidden, "index": index, }: { + name: string; + type?: enum_type; + mode?: enum_mode; + default?: any; + info?: string; + hidden?: boolean; + index: int; + }): class_argument; + /** + * @author fenris + */ + static volatile({ "name": name, "type": type, "mode": mode, "default": default_, "info": info, "hidden": hidden, "indicators_short": indicators_short, "indicators_long": indicators_long, }: { + name: string; + type?: enum_type; + mode?: enum_mode; + default?: any; + info?: string; + hidden?: boolean; + indicators_short: Array; + indicators_long: Array; + }): class_argument; + /** + * @author fenris + */ + check(): boolean; + /** + * @author fenris + */ + name_get(): string; + /** + * @author fenris + */ + kind_get(): enum_kind; + /** + * @author fenris + */ + type_get(): enum_type; + /** + * @author fenris + */ + mode_get(): enum_mode; + /** + * @author fenris + */ + default_get(): any; + /** + * @author fenris + */ + parameters_get(): Object; + /** + * @author fenris + */ + hidden_get(): boolean; + /** + * @author fenris + */ + toString(): string; + /** + * @author fenris + */ + indicator_main(): string; + /** + * @author fenris + */ + pattern_value(): string; + /** + * @author fenris + */ + extract(raw: string): any; + /** + * @author fenris + */ + assign(data: Object, target: string, raw: string): void; + /** + * @author fenris + */ + make(data: Object, target: string): string; + /** + * @author fenris + */ + generate_help(): string; + } +} +declare namespace lib_plankton.args { + /** + * @author fenris + */ + var verbosity: int; + /** + * @author fenris + * @todo check validity + */ + class class_handler { + /** + * @author fenris + */ + protected arguments_: { + [name: string]: class_argument; + }; + /** + * @author fenris + */ + constructor(arguments_: { + [name: string]: class_argument; + }); + /** + * @author fenris + */ + filter(kind: enum_kind): { + [name: string]: class_argument; + }; + /** + * @author fenris + */ + read(environment: enum_environment, input: string, data?: { + [name: string]: any; + }): { + [name: string]: any; + }; + /** + * @author fenris + * @todo handle if the data object doesn't have the required field or the type is wrong or sth. + */ + write(environment: enum_environment, data: { + [name: string]: any; + }): string; + /** + * @desc manpage-like info-sheet + * @author fenris + */ + generate_help({ "programname": programname, "author": author, "description": description, "executable": executable, }: { + programname?: string; + author?: string; + description?: string; + executable?: string; + }): string; + } +} diff --git a/lib/plankton/plankton.js b/lib/plankton/plankton.js new file mode 100644 index 0000000..1120f34 --- /dev/null +++ b/lib/plankton/plankton.js @@ -0,0 +1,5427 @@ +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' + + +»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 . + */ +// } +/* +This file is part of »bacterio-plankton:base«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»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 . + */ +; +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' + + +»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 . + */ +/** + * @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' + + +»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 . + */ +/** + * @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' + + +»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 . + */ +/** + * @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 { + + |** + * @author frac + *| + read() : type_executor; + +} + */ +/** + * @author frac + */ +/* +export interface interface_writeable { + + |** + * @author frac + *| + write(value : type_value) : type_executor; + +} + */ +/* +This file is part of »bacterio-plankton:base«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»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 . + */ +var lib_maybe; +(function (lib_maybe) { + /** + * @author fenris + */ + function make_nothing() { + return { + "kind": "nothing", + "parameters": {} + }; + } + lib_maybe.make_nothing = make_nothing; + /** + * @author fenris + */ + function make_just(value) { + return { + "kind": "just", + "parameters": { + "value": value + } + }; + } + lib_maybe.make_just = make_just; + /** + * @author fenris + */ + function is_nothing(maybe) { + return (maybe.kind === "nothing"); + } + lib_maybe.is_nothing = is_nothing; + /** + * @author fenris + */ + function is_just(maybe) { + return (maybe.kind === "just"); + } + lib_maybe.is_just = is_just; + /** + * @author fenris + */ + function cull(maybe) { + if (!is_just(maybe)) { + var message = "cull from nothing"; + throw (new Error(message)); + } + else { + var value = maybe.parameters["value"]; + return value; + } + } + lib_maybe.cull = cull; + /** + * @author fenris + */ + function propagate(maybe, function_) { + if (!is_just(maybe)) { + } + else { + var value = maybe.parameters["value"]; + var maybe_ = function_(value); + return maybe_; + } + } + lib_maybe.propagate = propagate; +})(lib_maybe || (lib_maybe = {})); +/** + * @author fenris + */ +/*export*/ var class_maybe = /** @class */ (function () { + function class_maybe() { + } + /** + * @desc whether the wrapper is nothing + * @author fenris + */ + class_maybe.prototype.is_nothing = function () { + throw (new Error("not implemented: class_maybe.is_nothing")); + }; + /** + * @desc whether the wrapper is just + * @author fenris + */ + class_maybe.prototype.is_just = function () { + throw (new Error("not implemented: class_maybe.is_just")); + }; + /** + * @desc return the value, stored in the maybe-wrapper + * @author fenris + */ + class_maybe.prototype.cull = function () { + throw (new Error("not implemented: class_maybe.cull")); + }; + /** + * @author fenris + */ + class_maybe.prototype.toString = function () { + throw (new Error("not implemented: class_maybe.cull")); + }; + /** + * @author fenris + */ + class_maybe.prototype.distinguish = function (action_just, action_nothing) { + if (action_nothing === void 0) { action_nothing = function () { }; } + throw (new Error("not implemented: class_maybe.distinguish")); + }; + /** + * @author fenris + */ + class_maybe.prototype.propagate = function (action) { + throw (new Error("not implemented: class_maybe.propagate")); + }; + /** + * @desc [implementation] + * @author fenris + */ + class_maybe.prototype._show = function () { + return this.toString(); + }; + return class_maybe; +}()); +/** + * @author fenris + */ +/*export*/ var class_nothing = /** @class */ (function (_super) { + __extends(class_nothing, _super); + /** + * @author fenris + */ + function class_nothing(reason) { + if (reason === void 0) { reason = null; } + var _this = _super.call(this) || this; + _this.reason = reason; + return _this; + } + /** + * @author fenris + */ + class_nothing.prototype.is_nothing = function () { + return true; + }; + /** + * @author fenris + */ + class_nothing.prototype.is_just = function () { + return false; + }; + /** + * @author fenris + */ + class_nothing.prototype.cull = function () { + var message = "you shouldn't cull a nothing-value …"; + // lib_plankton.log.warn(message); + return null; + }; + /** + * @author fenris + */ + class_nothing.prototype.toString = function () { + return "<\u00B7>"; + }; + /** + * @author fenris + */ + class_nothing.prototype.reason_get = function () { + var content = ((this.reason == null) ? "·" : this.reason); + return "<- ".concat(content, " ->"); + }; + /** + * @author fenris + */ + class_nothing.prototype.distinguish = function (action_just, action_nothing) { + if (action_nothing === void 0) { action_nothing = function () { }; } + action_nothing(this.reason); + }; + /** + * @author fenris + */ + class_nothing.prototype.propagate = function (action) { + return (new class_nothing(this.reason)); + }; + return class_nothing; +}(class_maybe)); +/** + * @author fenris + */ +/*export*/ var class_just = /** @class */ (function (_super) { + __extends(class_just, _super); + /** + * @author fenris + */ + function class_just(value) { + var _this = _super.call(this) || this; + _this.value = value; + return _this; + } + /** + * @author fenris + */ + class_just.prototype.is_nothing = function () { + return false; + }; + /** + * @author fenris + */ + class_just.prototype.is_just = function () { + return true; + }; + /** + * @author fenris + */ + class_just.prototype.cull = function () { + return this.value; + }; + /** + * @author fenris + */ + class_just.prototype.toString = function () { + var content = instance_show(this.value); + return "<+ ".concat(content, " +>"); + }; + /** + * @author fenris + */ + class_just.prototype.distinguish = function (action_just, action_nothing) { + if (action_nothing === void 0) { action_nothing = function () { }; } + action_just(this.value); + }; + /** + * @author fenris + */ + class_just.prototype.propagate = function (action) { + return action(this.value); + }; + return class_just; +}(class_maybe)); +/* +This file is part of »bacterio-plankton:base«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»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 . + */ +/** + * @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 = {})); +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:log«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:log« 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:lang« 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:log«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var log; + (function (log) { + /** + */ + var enum_level; + (function (enum_level) { + enum_level[enum_level["debug"] = 0] = "debug"; + enum_level[enum_level["info"] = 1] = "info"; + enum_level[enum_level["notice"] = 2] = "notice"; + enum_level[enum_level["warning"] = 3] = "warning"; + enum_level[enum_level["error"] = 4] = "error"; + })(enum_level = log.enum_level || (log.enum_level = {})); + ; + /** + */ + function level_order(level1, level2) { + return (level1 <= level2); + } + log.level_order = level_order; + /** + */ + function level_show(level) { + switch (level) { + case enum_level.debug: return "debug"; + case enum_level.info: return "info"; + case enum_level.notice: return "notice"; + case enum_level.warning: return "warning"; + case enum_level.error: return "error"; + default: return "(unknown)"; + } + } + log.level_show = level_show; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:log« 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:lang« 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:lang«. If not, see . + */ +/** + * @deprecated + * @todo remove + */ +var lib_plankton; +(function (lib_plankton) { + var log; + (function (log) { + /** + * @author fenris + */ + /*export*/ var level_stack = [0]; + function level_push(level) { level_stack.push(level); } + log.level_push = level_push; + function level_pop() { if (level_stack.length > 1) { + level_stack.pop(); + } } + log.level_pop = level_pop; + function level_get() { return level_stack.slice(-1)[0]; } + /* + export function level_inc() : void {level_push(level_get()+1);} + export function level_dec() : void {level_push(level_get()-1);} + */ + /** + * @author fenris + */ + var indent_stack = [0]; + function indent_push(indent) { indent_stack.push(indent); } + log.indent_push = indent_push; + function indent_pop() { if (indent_stack.length > 1) { + indent_stack.pop(); + } } + log.indent_pop = indent_pop; + function indent_get() { return level_stack.slice(-1)[0]; } + function indent_inc() { level_push(level_get() + 1); } + log.indent_inc = indent_inc; + function indent_dec() { level_push(level_get() - 1); } + log.indent_dec = indent_dec; + /** + * @author fenris + */ + function write(_a) { + var message = _a["message"], _b = _a["type"], type = _b === void 0 ? null : _b, _c = _a["prefix"], prefix = _c === void 0 ? null : _c, _d = _a["level"], level = _d === void 0 ? 0 : _d, _e = _a["indent"], indent = _e === void 0 ? 0 : _e; + var entry = { + "level": ((type === null) + ? lib_plankton.log.enum_level.info + : { + "debug": lib_plankton.log.enum_level.debug, + "info": lib_plankton.log.enum_level.info, + "notice": lib_plankton.log.enum_level.notice, + "warning": lib_plankton.log.enum_level.warning, + "error": lib_plankton.log.enum_level.error + }[type]), + "incident": message, + "details": { + "prefix": prefix, + "level": level, + "indent": indent + } + }; + lib_plankton.log.add(entry); + } + log.write = write; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:log« 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:lang« 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:log«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var log; + (function (log) { + /** + */ + var class_channel = /** @class */ (function () { + function class_channel() { + } + return class_channel; + }()); + log.class_channel = class_channel; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:log« 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:lang« 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:log«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var log; + (function (log) { + /** + * output for writing log entries to stdout + */ + var class_channel_stdout = /** @class */ (function (_super) { + __extends(class_channel_stdout, _super); + function class_channel_stdout() { + return _super !== null && _super.apply(this, arguments) || this; + } + /** + */ + class_channel_stdout.prototype.add = function (entry) { + process.stdout.write(("<" + (new Date(Date.now())).toISOString().slice(0, 19) + ">") + + + " " + + + ("[" + log.level_show(entry.level) + "]") + + + " " + + + ("" + entry.incident + "") + + + ": " + + + JSON.stringify(entry.details, undefined, " ") + + + "\n"); + }; + return class_channel_stdout; + }(log.class_channel)); + log.class_channel_stdout = class_channel_stdout; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:log« 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:lang« 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:log«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var log; + (function (log) { + /** + */ + var class_channel_file = /** @class */ (function (_super) { + __extends(class_channel_file, _super); + /** + * [constructor] + */ + function class_channel_file(path) { + var _this = _super.call(this) || this; + _this.path = path; + return _this; + } + /** + */ + class_channel_file.prototype.add = function (entry) { + var _this = this; + var nm_fs = require("fs"); + nm_fs.writeFile(this.path, { + "flag": "a+" + }, (("<" + (new Date(Date.now())).toISOString().slice(0, 19) + ">") + + + " " + + + ("[" + log.level_show(entry.level) + "]") + + + " " + + + ("" + entry.incident + "") + + + ": " + + + JSON.stringify(entry.details, undefined, " ") + + + "\n"), function (error) { + process.stderr.write('-- [plankton] could not add log entry to file ' + _this.path + "\n"); + }); + }; + return class_channel_file; + }(log.class_channel)); + log.class_channel_file = class_channel_file; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:log« 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:lang« 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:log«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var log; + (function (log) { + /** + * output for desktop notifications via "libnotify" + */ + var class_channel_notify = /** @class */ (function (_super) { + __extends(class_channel_notify, _super); + function class_channel_notify() { + return _super !== null && _super.apply(this, arguments) || this; + } + /** + */ + class_channel_notify.prototype.add = function (entry) { + var nm_child_process = require("child_process"); + var command = ("notify-send" + + + " " + + + ("'" + + + ("[" + log.level_show(entry.level) + "]") + + + " " + + + entry.incident + + + "'") + + + " " + + + ("'" + + + (Object.keys(entry.details) + .map(function (key) { return (key + ": " + JSON.stringify(entry.details[key])); }) + .join("\n")) + + + "'")); + nm_child_process.exec(command, function (error, stdout, stderr) { + // do noting + }); + }; + return class_channel_notify; + }(log.class_channel)); + log.class_channel_notify = class_channel_notify; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:log« 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:lang« 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:log«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var log; + (function (log) { + /** + * decorator for filtering out log entries below a certain level threshold + */ + var class_channel_minlevel = /** @class */ (function (_super) { + __extends(class_channel_minlevel, _super); + /** + */ + function class_channel_minlevel(core, threshold) { + var _this = _super.call(this) || this; + _this.core = core; + _this.threshold = threshold; + return _this; + } + /** + */ + class_channel_minlevel.prototype.add = function (entry) { + if (!log.level_order(this.threshold, entry.level)) { + // do nothing + } + else { + this.core.add(entry); + } + }; + return class_channel_minlevel; + }(log.class_channel)); + log.class_channel_minlevel = class_channel_minlevel; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:log« 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:lang« 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:log«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var log; + (function (log) { + /** + */ + function translate_level(level_string) { + return { + "debug": log.enum_level.debug, + "info": log.enum_level.info, + "notice": log.enum_level.notice, + "warning": log.enum_level.warning, + "error": log.enum_level.error + }[level_string]; + } + /** + */ + function channel_make(description) { + var _a, _b, _c, _d; + switch (description.kind) { + default: { + throw (new Error("unhandled log channel kind: " + description.kind)); + break; + } + case "stdout": { + return (new log.class_channel_minlevel(new log.class_channel_stdout(), translate_level((_a = description.data["threshold"]) !== null && _a !== void 0 ? _a : "debug"))); + break; + } + case "file": { + return (new log.class_channel_minlevel(new log.class_channel_file((_b = description.data["path"]) !== null && _b !== void 0 ? _b : "/tmp/plankton.log"), translate_level((_c = description.data["threshold"]) !== null && _c !== void 0 ? _c : "debug"))); + break; + } + case "notify": { + return (new log.class_channel_minlevel(new log.class_channel_notify(), translate_level((_d = description.data["threshold"]) !== null && _d !== void 0 ? _d : "debug"))); + break; + } + } + } + log.channel_make = channel_make; + /** + */ + function conf_default() { + return [ + new log.class_channel_minlevel(new log.class_channel_stdout(), log.enum_level.notice), + new log.class_channel_minlevel(new log.class_channel_notify(), log.enum_level.error), + ]; + } + log.conf_default = conf_default; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:log« 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:lang« 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:log«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var log; + (function (log) { + /** + */ + var _channel_stack = null; + /** + * pushes a new configuration on the stack and activates it + */ + function conf_push(channels) { + if (_channel_stack === null) { + _channel_stack = []; + } + _channel_stack.push(channels); + } + log.conf_push = conf_push; + /** + * pops the current active configuration from the stack + */ + function conf_pop() { + if (_channel_stack.length > 0) { + _channel_stack.pop(); + } + else { + // do nothing + } + } + log.conf_pop = conf_pop; + /** + * makes the logging system ready + */ + function setup() { + if (_channel_stack === null) { + _channel_stack = []; + conf_push(log.conf_default()); + } + else { + // do nothing + } + } + /** + * consumes a log entry, i.e. sends it to the currently active outputs + */ + function add(entry) { + setup(); + _channel_stack.slice(-1)[0].forEach(function (channel) { return channel.add(entry); }); + } + log.add = add; + /** + */ + function debug(incident, details) { + if (details === void 0) { details = {}; } + add({ "level": log.enum_level.debug, "incident": incident, "details": details }); + } + log.debug = debug; + /** + */ + function info(incident, details) { + if (details === void 0) { details = {}; } + add({ "level": log.enum_level.info, "incident": incident, "details": details }); + } + log.info = info; + /** + */ + function notice(incident, details) { + if (details === void 0) { details = {}; } + add({ "level": log.enum_level.notice, "incident": incident, "details": details }); + } + log.notice = notice; + /** + */ + function warning(incident, details) { + if (details === void 0) { details = {}; } + add({ "level": log.enum_level.warning, "incident": incident, "details": details }); + } + log.warning = warning; + /** + */ + function error(incident, details) { + if (details === void 0) { details = {}; } + add({ "level": log.enum_level.error, "incident": incident, "details": details }); + } + log.error = error; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:string«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:string« 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:string« 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:string«. If not, see . + */ +var plain_text_to_html = function (text) { + let ret = text; + ret = ret.replace(/ /g, "  "); // convert multiple whitespace to forced ones + ret = ret.split("\n").join("
"); + return ret; +}; +/** + * @desc makes a valid + */ +var format_sentence = function (str, rtl = false, caseSense = true) { + if (str === "") { + return str; + } + else { + let marks = { + ".": true, + "?": true, + "!": true + }; + let default_mark = "."; + let ret = str.split(""); + if (!rtl) { + ret[0] = ret[0].toLocaleUpperCase(); + if (!(ret[ret.length - 1] in marks)) { + ret.push(default_mark); + } + } + else { + ret[ret.length - 1] = ret[ret.length - 1].toLocaleUpperCase(); + if (!(ret[0] in marks)) { + ret.unshift(default_mark); + } + } + return ret.join(""); + } +}; +var fill_string_template = function (template_string, object, fabric = function (object, key) { return object[key]; }, delimiter = "%", default_string = null, sloppy) { + function get_tags(str) { + let r = new RegExp(delimiter + "[^\\s^" + delimiter + "]+" + delimiter, "gi"); + return ((str.match(r) || []).map(function (e) { + return e.slice(delimiter.length, e.length - delimiter.length); + })); + } + function replace_tag(str, tag, value) { + let r = new RegExp(delimiter + tag + delimiter, "gi"); + return str.replace(r, value); + } + function replace_tags(str, obj) { + return (get_tags(str).reduce(function (ret, key) { + let value = ""; + try { + value = fabric(obj, key); + if ((!sloppy && (value === void 0)) || (sloppy && (value == void 0))) { + value = default_string; + } + } + catch (e) { + console.warn("invalid placeholder " + key); + value = default_string; + } + return replace_tag(ret, key, value); + }, str)); + } + return replace_tags(template_string, object); +}; +var make_string_template = function (_template, _fabrics = {}) { + function replace_tag(str, tag, value) { + var r = new RegExp("%" + tag + "%", "gi"); + return str.replace(r, value); + } + function replace_tags(str, obj) { + return (Object.keys(obj).reduce(function (ret, key) { + return replace_tag(ret, key, _fabrics[key] || obj[key]); + }, str)); + } + return (function (tags) { + return replace_tags(_template, tags); + }); +}; +var make_eml_header = (function () { + let _template = ""; + _template += "From: %from%\n"; + _template += "To: %recipient%\n"; + _template += "Subject: %subject%\n"; + _template += "X-Mailer: greenscale-plankton.emlgen\n"; + return make_string_template(_template); +})(); +var make_eml_body = (function () { + let exports = {}; + exports["simple_body"] = make_string_template("Content-Type: %contenttype%\n\n%body%\n\n"); + // very basic implementation + // parts = [{contenttype:"text/html; charset=UTF-8", body: "

foo

" }, {...}] + exports["body_boundrary"] = function (parts, boundrary) { + let _template = ""; + _template += "--%boundrary%\n"; + _template += "Content-Type: %contenttype%\n\n%body%\n\n"; + //_template += "--%boundrary%--\n\n"; + let maker = make_string_template(_template); + return (parts.reduce(function (prev, curr) { + curr.boundrary = boundrary; + return [prev, maker(curr)].join(""); + }, "")); + }; + // body must be base64 encoded! + exports["attachment_boundrary"] = function (parts, boundrary) { + let _template = ""; + _template += "--%boundrary%\n"; + _template += "Content-Type: %contenttype%\n"; + _template += "Content-Transfer-Encoding: base64\n"; + _template += "Content-Disposition: %disposition%; filename=\"%name%\"\n\n"; + _template += "%body%\n\n"; + //_template += "--%boundrary%--\n\n"; + let maker = make_string_template(_template); + return (parts.reduce(function (prev, curr) { + curr.boundrary = boundrary; + if (curr.disposition === void 0) + curr.disposition = "inline"; + return [prev, maker(curr)].join(""); + }, "")); + }; + exports["gen_boundrary"] = function () { + return ("xxxxxxxxxxxxxxxxxxxxxx".replace(/[xy]/g, function (c) { + let r = crypto.getRandomValues(new Uint8Array(1))[0] % 16 | 0, v = c == "x" ? r : (r & 0x3 | 0x8); + return v.toString(16); + })); + }; + // simple implementation without alternatives (old rfc) + exports["complete_boundrary"] = function (bodyparts, attachments) { + let ret = ""; + let boundrary = exports["gen_boundrary"](); + ret += exports["body_boundrary"](bodyparts, boundrary); + ret += exports["attachment_boundrary"](attachments, boundrary); + ret += "--" + boundrary + "--\n\nINVISIBLE!!!!"; + return (exports["simple_body"]({ + "contenttype": sprintf("multipart/mixed; boundary=%s", [boundrary]), + "body": ret + })); + }; + return exports; +})(); +/* +This file is part of »bacterio-plankton:string«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:string« 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:string« 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:string«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var string; + (function (string) { + /** + * @author fenris + */ + const hexdigits = 4; + /** + * @author fenris + */ + const index_max = (1 << (4 * hexdigits)); + /** + * @author fenris + */ + var index_is = 0; + /** + * @author neuc,frac + */ + function empty(str) { + return (str.trim() === ""); + } + string.empty = empty; + /** + * @desc returns a unique string + * @param {string} prefix an optional prefix for the generated string + * @return {string} + * @author fenris + */ + function generate(prefix = "string_") { + if (index_is > index_max) { + throw (new Error("[string_generate] out of valid indices")); + } + else { + return string.sprintf(prefix + "%0" + hexdigits.toString() + "X", [index_is++]); + } + } + string.generate = generate; + /** + * @desc splits a string, but returns an empty list, if the string is empty + * @param {string} chain + * @param {string} separator + * @return {Array} + * @author fenris + */ + function split(chain, separator = " ") { + if (chain.length == 0) { + return []; + } + else { + return chain.split(separator); + } + } + string.split = split; + /** + * @author neu3no + */ + function explode(str, needle, max) { + let temp = str.split(needle); + const right = temp.splice(max - 1); + temp.push(right.join(needle)); + return temp; + } + string.explode = explode; + /** + * @desc concats a given word with itself n times + * @param {string} word + * @param {int} + * @return {string} + * @author fenris + */ + function repeat(word, count) { + // return ((count == 0) ? "" : (word + repeat(word, count-1))); + let result = ""; + for (let n = 0; n < count; n += 1) { + result += word; + } + return result; + } + string.repeat = repeat; + /** + * @desc lengthens a string by repeatedly appending or prepending another string + * @param {string} word the string to pad + * @param {int} length the length, which the result shall have + * @param {string} symbol the string, which will be added (multiple times) + * @param {boolean} [prepend]; whether to prepend (~true) or append (~false); default: false + * @return {string} the padded string + * @author fenris + */ + function pad(word, length, symbol = " ", mode = "append") { + switch (mode) { + case "prepend": { + // insert symbols only at the beginning + while (word.length < length) + word = symbol + word; + return word.substring(word.length - length); + break; + } + case "append": { + // insert symbols only at the end + while (word.length < length) + word = word + symbol; + return word.substring(0, length); + break; + } + case "widen": { + // insert symbols at both sides + let left = (((length - word.length) & 1) === 0); + while (word.length < length) { + word = (left + ? (symbol + word) + : (word + symbol)); + left = (!left); + } + return word.substring(0, length); + break; + } + default: { + const message = ("unhandled mode '" + mode + "'"); + console.warn(message); + return word; + break; + } + } + } + string.pad = pad; + /** + * @desc checks if a given string conttains a certain substring + * @param {string} string + * @param {string} part + * @return {boolean} + * @author fenris + */ + function contains(chain, part) { + if (typeof (chain) !== "string") { + return false; + } + return (chain.indexOf(part) >= 0); + } + string.contains = contains; + /** + * @desc checks if a given string starts with a certain substring + * @param {string} string + * @param {string} part + * @return {boolean} + * @author fenris + */ + function startsWith(chain, part) { + if (typeof (chain) !== "string") { + return false; + } + // return (string.indexOf(part) === 0); + return ((function (m, n) { + if (n === 0) { + return true; + } + else { + if (m === 0) { + return false; + } + else { + return ((chain[0] == part[0]) + && + startsWith(chain.substring(1), part.substring(1))); + } + } + })(chain.length, part.length)); + } + string.startsWith = startsWith; + /** + * @desc checks if a given string ends with a certain substring + * @param {string} string + * @param {string} part + * @return {boolean} + * @author fenris + */ + function endsWith(chain, part) { + if (typeof (chain) !== "string") { + return false; + } + // return (string.lastIndexOf(part) === string.length-part.length); + return ((function (m, n) { + if (n === 0) { + return true; + } + else { + if (m === 0) { + return false; + } + else { + // console.info(("(" + string[m-1] + " == " + part[n-1] + ")") + " = " + String(string[m-1] == part[n-1])); + return ((chain[m - 1] === part[n - 1]) + && + endsWith(chain.substring(0, m - 1), part.substring(0, n - 1))); + } + } + })(chain.length, part.length)); + } + string.endsWith = endsWith; + /** + * @desc count the occourrences of a string in a string + * @param string haystack_string the string wich should be examined + * @param string needle_string the string which should be counted + * @author neuc + */ + function count_occourrences(haystack_string, needle_string, check_escape) { + let cnt = 0; + let pos = -1; + do { + pos = haystack_string.indexOf(needle_string, pos + 1); + if ((!check_escape) || (haystack_string[pos - 1] != "\\")) { + cnt++; + } + } while (pos >= 0); + return (cnt - 1); + } + string.count_occourrences = count_occourrences; + /** + * @author fenris + */ + function replace(str, replacements, options = {}) { + options = Object.assign({}, options); + let result = str; + replacements.forEach(replacement => { + lib_plankton.log.debug("lib_plankton.string.replace", { + "from": replacement.from, + "to": replacement.to, + }); + result = result.replace(new RegExp(replacement.from, "g"), replacement.to); + }); + return result; + } + string.replace = replace; + /** + * @desc replaces occurences of "${name}" in a string by the corresponding values of an argument object + * @author fenris + */ + function coin(str, args, options = {}) { + options = Object.assign({ + "legacy": false, + "open": "{{", + "close": "}}", + }, options); + Object.keys(args).forEach((key) => { + // old syntax + { + if (options.legacy) { + const value = args[key]; + const regexp_argument = new RegExp("\\${" + key + "}", "g"); + lib_plankton.log.debug("lib_plankton.string.coin", { + "key": key, + "regex": regexp_argument.toString(), + "value": value, + }); + str = str.replace(regexp_argument, value); + } + } + // new syntax + { + const value = args[key]; + const regexp_argument = new RegExp(options.open + key + options.close, "g"); + lib_plankton.log.debug("lib_plankton.string.coin", { + "key": key, + "regex": regexp_argument.toString(), + "value": value, + }); + str = str.replace(regexp_argument, value); + } + }); + return str; + } + string.coin = coin; + /** + * @author fenris + */ + function cut(str, length, delimiter = "…") { + if (str.length <= length) { + return str; + } + else { + return (str.slice(0, length - delimiter.length) + delimiter); + } + } + string.cut = cut; + })(string = lib_plankton.string || (lib_plankton.string = {})); +})(lib_plankton || (lib_plankton = {})); +/** + * @deprecated + */ +var lib_string; +(function (lib_string) { + lib_string.empty = lib_plankton.string.empty; + lib_string.generate = lib_plankton.string.generate; + lib_string.split = lib_plankton.string.split; + lib_string.explode = lib_plankton.string.repeat; + lib_string.repeat = lib_plankton.string.repeat; + lib_string.pad = lib_plankton.string.pad; + lib_string.contains = lib_plankton.string.contains; + lib_string.startsWith = lib_plankton.string.startsWith; + lib_string.endsWith = lib_plankton.string.endsWith; + lib_string.count_occourrences = lib_plankton.string.count_occourrences; + lib_string.coin = lib_plankton.string.coin; + lib_string.stance = lib_plankton.string.coin; + lib_string.cut = lib_plankton.string.cut; +})(lib_string || (lib_string = {})); +/* +This file is part of »bacterio-plankton:string«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:string« 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:string« 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:string«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var string; + (function (string) { + var pattern = /%([-+#0 ]*)([0-9]*)[\.]{0,1}([0-9]*)([\w]{1})/; + var gpattern = /%([-+#0 ]*)([0-9]*)[\.]{0,1}([0-9]*)([\w]{1})/g; + function split_format(format) { + var tmp = format.match(pattern); + if (tmp === null) + return null; + return { + 'flags': tmp[1].split(""), + 'width': Number(tmp[2]), + 'precision': tmp[3] === '' ? null : Number(tmp[3]), + 'specifier': tmp[4], + 'string': format + }; + } + function make_err(format, arg, should) { + return ("[sprintf]" + " " + "argument for '" + format.string + "' has to be '" + should + "' but '" + arg + "' is '" + typeof arg + "'!"); + } + function test_arg(format, arg, should) { + if (typeof arg !== should) { + console.warn(make_err(format, arg, should)); + return false; + } + return true; + } + function string_fill(str, char, len, left) { + while (str.length < len) { + if (left) { + str += char; + } + else { + str = char + str; + } + } + return str; + } + /** + * the known_parameters are used to parse the different identifiers for the welln known syntax: + * flag width precision identifier + * %{[0#+- ]}{[0-9]*}.{[0-9]*}[fFdiueEgGsoxXaAsn] + * flags: + * 0 - fill with '0' instead of ' ' if the string length < width + * # - not implemented + * - - left-justified -> fill on the right side to reach width + * + - force using '+' on positive numbers + * ' ' - add a single space before positive numbers + * + * identifiers + * %f, %F - interpret given number as float, width: the minimal total width (fill with ' ' or '0' if the + * resulting string is too short, precision: cut more then given decimal places + * %d, %i, %u - interpret number as integer, decimal places will be cut. width: like float, precision: + * fill with '0' on right side until length given in precision is reached + * %e - interpret as float and write as scientifical number, width & precision like in float + * %E - same es %e but uppercase 'E' + * %g - use the shortest string of %f or %e + * %G - use the shortest string of %E or %E + * %s - simply print a string + * %o - print the given number in octal notation + * %x - print the given number in hex notation + * %X - same as %x but with uppercase characters + * %a - alias to %x + * %A - alias to %X + * %n - just print nothing + * @type {{}} + */ + var known_params = {}; + known_params["f"] = function (format, arg) { + if (!test_arg(format, arg, "number")) + return "Ø"; + var tmp = Math.abs(arg); + var sign = (arg < 0) ? -1 : 1; + var tmp_result = null; + if (format.precision !== null) { + tmp = Math.floor(Math.pow(10, format.precision) * tmp) / Math.pow(10, format.precision); + var tmp_ = (tmp * sign).toString().split("."); + if (tmp_.length === 1) + tmp_.push(""); + tmp_[1] = string_fill(tmp_[1], "0", format.precision, true); + tmp_result = tmp_.join("."); + } + else { + tmp_result = (sign * tmp).toString(); + } + if ((format.flags.indexOf(" ") >= 0) && (arg >= 0)) { + tmp_result = " " + tmp; + } + else if ((format.flags.indexOf("+") >= 0) && (arg >= 0)) { + tmp_result = "+" + tmp; + } + tmp_result = string_fill(tmp, (format.flags.indexOf("0") >= 0) ? "0" : " ", format.width, (format.flags.indexOf("-") >= 0)); + return tmp_result; + }; + known_params["F"] = known_params["f"]; + known_params["d"] = function (format, arg) { + if (!test_arg(format, arg, 'number')) + return 'Ø'; + var tmp = (((arg < 0 && format.specifier !== 'u') ? -1 : 1) * Math.floor(Math.abs(arg))).toString(); + if ((format.specifier === 'd' || format.specifier === 'i') && format.flags.indexOf(' ') >= 0 && arg >= 0) { + tmp = ' ' + tmp; + } + else if ((format.specifier === 'd' || format.specifier === 'i') && format.flags.indexOf('+') >= 0 && arg >= 0) { + tmp = '+' + tmp; + } + tmp = string_fill(tmp, format.flags.indexOf('0') >= 0 ? '0' : ' ', format.width, format.flags.indexOf('-') >= 0); + tmp = string_fill(tmp, '0', format.precision === null ? 0 : format.precision, false); + return tmp; + }; + known_params["i"] = known_params["d"]; + known_params["u"] = known_params["d"]; + known_params["e"] = function (format, arg) { + if (!test_arg(format, arg, 'number')) + return 'Ø'; + var tmp = arg.toExponential(format.precision === null ? undefined : format.precision).toString(); + if (format.flags.indexOf(' ') >= 0 && arg >= 0) { + tmp = ' ' + tmp; + } + else if (format.flags.indexOf('+') >= 0 && arg >= 0) { + tmp = '+' + tmp; + } + tmp = string_fill(tmp, format.flags.indexOf('0') >= 0 ? '0' : ' ', format.width, format.flags.indexOf('-') >= 0); + return tmp; + }; + known_params["E"] = function (format, arg) { + return known_params["e"](format, arg).toUpperCase(); + }; + known_params["g"] = function (format, arg) { + if (!test_arg(format, arg, 'number')) + return 'Ø'; + var tmpf = known_params["f"](format, arg); + var tmpe = known_params["e"](format, arg); + if (tmpf.length < tmpe.length) { + return tmpf; + } + else { + return tmpe; + } + }; + known_params["G"] = function (format, arg) { + return known_params["g"](format, arg).toUpperCase(); + }; + known_params["s"] = function (format, arg) { + if (!test_arg(format, arg, 'string')) + return 'o.O'; + var tmp = format.precision !== null ? arg.substr(0, format.precision) : arg; + tmp = string_fill(tmp, format.flags.indexOf('0') >= 0 ? '0' : ' ', format.width, format.flags.indexOf('-') >= 0); + return tmp; + }; + known_params["o"] = function (format, arg) { + if (!test_arg(format, arg, 'number')) + return 'Ø'; + var tmp = Math.floor(Math.round(Math.abs(arg))) * ((arg < 0) ? -1 : 1); + return known_params["s"](format, tmp.toString(8)); + }; + known_params["x"] = function (format, arg) { + if (!test_arg(format, arg, 'number')) + return 'Ø'; + var tmp = Math.floor(Math.round(Math.abs(arg))) * ((arg < 0) ? -1 : 1); + return known_params["s"](format, tmp.toString(16)); + }; + known_params["a"] = known_params["x"]; + known_params["X"] = function (format, arg) { + if (!test_arg(format, arg, 'number')) + return 'Ø'; + return known_params["x"](format, arg).toUpperCase(); + }; + known_params["A"] = known_params["X"]; + known_params["c"] = function (format, arg) { + var tmp = ""; + if (typeof arg === "number") { + tmp = String.fromCharCode(arg); + } + else if ((typeof arg === "string") && (arg.length === 1)) { + tmp = arg[0]; + } + else { + console.warn(make_err(format, arg, "number|string") + " and if string it needs to have the length of 1!"); + } + return known_params["s"](format, tmp); + }; + known_params["n"] = function () { + return ""; + }; + var decompose = function (chain, regexp) { + var result = regexp.exec(chain); + if (result == null) { + return null; + } + else { + var front = chain.substring(0, result.index); + var back = chain.substring(result.index + result[0].length); + return { "front": front, "match": result[0], "back": back }; + } + }; + /** + * an implementation of c sprintf + * @param {string} string format string + * @param {array} args arguments which should be filled into + * @returns {string} + */ + string.sprintf = function (input, args = [], original = null) { + if (original == null) + original = input; + var components = decompose(input, pattern); + if (components == null) { + if (args.length > 0) { + console.warn("[sprintf] superfluous arguments while formatting '" + original + "': ", args); + } + return input; + } + else { + var arg; + var rest; + if (args.length > 0) { + arg = args[0]; + rest = args.slice(1); + } + else { + console.warn("[sprintf] out of arguments while formatting '" + original + "'"); + arg = null; + rest = []; + return input; + } + var fmt = split_format(components["match"]); + return (components["front"] + + known_params[fmt.specifier](fmt, arg) + + string.sprintf(components["back"], rest, original)); + } + }; + /** + * an implementation of c printf + * @param {string} string format string + * @param {array} args arguments which should be filled into + * @returns {string} + */ + function printf(format, args) { + console.log(string.sprintf(format, args)); + } + string.printf = printf; + })(string = lib_plankton.string || (lib_plankton.string = {})); +})(lib_plankton || (lib_plankton = {})); +var sprintf = lib_plankton.string.sprintf; +var printf = lib_plankton.string.printf; +/* +This file is part of »bacterio-plankton:string«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:string« 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:string« 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:string«. If not, see . + */ +var make_logger = (function () { + var _loggers = {}; + var make_logger = function (prefix, current_loglevel) { + var log = []; + var level = [ + "LOG", "INFO", "WARNING", "DEBUG" + ]; + var logger = function (obj, lvl) { + var txt = obj.txt || obj; + if (lvl == void 0) + lvl = 0; + var date = new Date(); + log.push({ + "message": sprintf("%s [%s:%s] %s", [date.toString(), level[lvl], prefix, txt]), + "timeStamp": +(date) + }); + if (lvl <= current_loglevel) { + var msg = ["[" + prefix + "]", txt]; + if (obj.arg) + msg = ["[" + prefix + "]"].concat(Array.prototype.slice.call(obj.arg)); + if (lvl === 0) + console["_log"].apply(console, msg); + else if (lvl === 1) + console["_info"].apply(console, msg); + else if (lvl === 2) + console["_warn"].apply(console, msg); + else if (lvl >= 3) + console["_log"].apply(console, msg); + } + }; + _loggers[prefix] = { + "logger": logger, + "log": log + }; + return logger; + }; + make_logger["loggers"] = _loggers; + make_logger["complete_log"] = function () { + var logs = Object.keys(_loggers) + .reduce(function (p, c) { + return [].concat(p, _loggers[c].log); + }, []); + logs.sort(function (x, y) { + return ((x.timeStamp > y.timeStamp) ? -1 : +1); + }); + return logs.map(function (x, i, a) { + return x.message; + }); + }; + if ( /*!track_exports*/true) { + var _log_all = function (log, lvl, next = function () { }) { + return function () { + var msg = []; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] === "string") { + msg.push(arguments[i]); + } + else { + msg.push(JSON.stringify(arguments[i])); + } + } + var obj = { + txt: msg.join("\t"), + arg: arguments + }; + log(obj, lvl); + next(); + }; + }; + { + var __warn = make_logger("deprecated console.warn", 99); + var __error = make_logger("deprecated console.error", 99); + var __log = make_logger("deprecated console.log", 99); + var __info = make_logger("deprecated console.info", 99); + // bad ass + console["_log"] = console.log; + console["_error"] = console.error; + console["_warn"] = console.warn; + console["_info"] = console.info; + /* + console["log"] = _log_all(__log, 0); + console["error"] = _log_all(__error, 2); + console["warn"] = _log_all(__warn, 2); + console["info"] = _log_all(__info, 0); + */ + } + /* + { + make_logger["send_log"] = function(){ + eml_log( + function () { + alert("fehlerbericht wurde gesendet!"); + } + ); + }; + var error_log = make_logger("global.error", 99); + window.onerror = _log_all( + error_log, + 1, + function(){ + if (global_config == undefined) { + return false; + } + if (global_config.report_error) { + make_logger["send_log"](); + } + } + ); + } + */ + } + return make_logger; +})(); +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« 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:code« 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:code«. If not, see . + */ +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« 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:code« 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:code«. If not, see . + */ +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« 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:code« 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:code«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var code; + (function (code) { + /** + * @author fenris + */ + function inverse_encode(decode, to) { + return decode(to); + } + code.inverse_encode = inverse_encode; + /** + * @author fenris + */ + function inverse_decode(encode, from) { + return encode(from); + } + code.inverse_decode = inverse_decode; + })(code = lib_plankton.code || (lib_plankton.code = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« 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:code« 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:code«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var code; + (function (code) { + /** + * @author fenris + */ + var class_code_inverse = /** @class */ (function () { + /** + * @author fenris + */ + function class_code_inverse(subject) { + this.subject = subject; + } + /** + * @implementation + * @author fenris + */ + class_code_inverse.prototype.encode = function (to) { + var _this = this; + return code.inverse_encode(function (x) { return _this.subject.decode(x); }, to); + }; + /** + * @implementation + * @author fenris + */ + class_code_inverse.prototype.decode = function (from) { + var _this = this; + return code.inverse_decode(function (x) { return _this.subject.encode(x); }, from); + }; + return class_code_inverse; + }()); + code.class_code_inverse = class_code_inverse; + })(code = lib_plankton.code || (lib_plankton.code = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« 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:code« 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:code«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var code; + (function (code) { + /** + * @author fenris + */ + function pair_encode(encode_first, encode_second, from) { + var between = encode_first(from); + var to = encode_second(between); + return to; + } + code.pair_encode = pair_encode; + /** + * @author fenris + */ + function pair_decode(decode_first, decode_second, to) { + var between = decode_second(to); + var from = decode_first(between); + return from; + } + code.pair_decode = pair_decode; + })(code = lib_plankton.code || (lib_plankton.code = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« 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:code« 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:code«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var code; + (function (code) { + /** + * @author fenris + */ + var class_code_pair = /** @class */ (function () { + /** + * @author fenris + */ + function class_code_pair(first, second) { + this.first = first; + this.second = second; + } + /** + * @implementation + * @author fenris + */ + class_code_pair.prototype.encode = function (from) { + var _this = this; + return code.pair_encode(function (x) { return _this.first.encode(x); }, function (x) { return _this.second.encode(x); }, from); + }; + /** + * @implementation + * @author fenris + */ + class_code_pair.prototype.decode = function (to) { + var _this = this; + return code.pair_decode(function (x) { return _this.first.decode(x); }, function (x) { return _this.second.decode(x); }, to); + }; + return class_code_pair; + }()); + code.class_code_pair = class_code_pair; + })(code = lib_plankton.code || (lib_plankton.code = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« 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:code« 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:code«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var code; + (function (code) { + /** + * @author fenris + */ + function chain_encode(encode_links, from) { + var value = from; + encode_links + .forEach(function (link) { + value = link(value); + }); + return value; + } + code.chain_encode = chain_encode; + /** + * @author fenris + */ + function chain_decode(decode_links, to) { + var value = to; + decode_links + .reverse() + .forEach(function (link) { + value = link(value); + }); + return value; + } + code.chain_decode = chain_decode; + })(code = lib_plankton.code || (lib_plankton.code = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« 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:code« 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:code«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var code; + (function (code) { + /** + * @author fenris + */ + var class_code_chain = /** @class */ (function () { + /** + * @author fenris + */ + function class_code_chain(links) { + this.links = links; + } + /** + * @implementation + * @author fenris + */ + class_code_chain.prototype.encode = function (from) { + return code.chain_encode(this.links.map(function (link) { return (function (x) { return link.encode(x); }); }), from); + }; + /** + * @implementation + * @author fenris + */ + class_code_chain.prototype.decode = function (to) { + return code.chain_decode(this.links.map(function (link) { return (function (x) { return link.decode(x); }); }), to); + }; + return class_code_chain; + }()); + code.class_code_chain = class_code_chain; + })(code = lib_plankton.code || (lib_plankton.code = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« 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:code« 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:code«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var code; + (function (code) { + /** + * @author Christian Fraß + */ + function flatten_encode(from, keys) { + if (keys === void 0) { keys = null; } + if (keys === null) { + if (from.length > 0) { + keys = Object.keys(from[0]); + } + else { + throw (new Error("encoding impossible")); + } + } + return { + "keys": keys, + "data": from.map(function (line) { return keys.map(function (name) { return line[name]; }); }) + }; + } + code.flatten_encode = flatten_encode; + /** + * @author Christian Fraß + */ + function flatten_decode(to) { + return (to.data + .map(function (dataset) { + var dataset_ = {}; + dataset + .forEach(function (value, index) { + var name = to.keys[index]; + dataset_[name] = value; + }); + return dataset_; + })); + } + code.flatten_decode = flatten_decode; + })(code = lib_plankton.code || (lib_plankton.code = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« 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:code« 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:code«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var code; + (function (code) { + /** + * @author fenris + */ + var class_code_flatten = /** @class */ (function () { + /** + * @author fenris + */ + function class_code_flatten() { + } + /** + * @implementation + * @author fenris + */ + class_code_flatten.prototype.encode = function (x) { + return code.flatten_encode(x); + }; + /** + * @implementation + * @author fenris + */ + class_code_flatten.prototype.decode = function (x) { + return code.flatten_decode(x); + }; + return class_code_flatten; + }()); + code.class_code_flatten = class_code_flatten; + })(code = lib_plankton.code || (lib_plankton.code = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:json«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:json« 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:json« 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:json«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var json; + (function (json) { + /** + * @author fenris + */ + function encode(x, formatted = false) { + return JSON.stringify(x, undefined, formatted ? "\t" : undefined); + } + json.encode = encode; + /** + * @author fenris + */ + function decode(x) { + return JSON.parse(x); + } + json.decode = decode; + })(json = lib_plankton.json || (lib_plankton.json = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:json«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:json« 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:json« 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:json«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var json; + (function (json) { + /** + * @author fenris + */ + class class_json { + /** + * @author fenris + */ + constructor() { + } + /** + * @implementation + * @author fenris + */ + encode(x) { + return json.encode(x); + } + /** + * @implementation + * @author fenris + */ + decode(x) { + return json.decode(x); + } + } + json.class_json = class_json; + })(json = lib_plankton.json || (lib_plankton.json = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:file«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:file« 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:file« 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:file«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var file; + (function (file) { + /** + * @author fenris + */ + function read(path) { + var nm_fs = require("fs"); + return (new Promise(function (resolve, reject) { + nm_fs.readFile(path, { + "encoding": "utf8", + "flag": "r", + }, function (error, content) { + if (error == null) { + resolve(content); + } + else { + reject(error); + } + }); + })); + } + file.read = read; + /** + * @author fenris + */ + function read_buffer(path) { + var nm_fs = require("fs"); + return (new Promise(function (resolve, reject) { + nm_fs.readFile(path, { + "flag": "r", + }, function (error, content) { + if (error == null) { + resolve(content); + } + else { + reject(error); + } + }); + })); + } + file.read_buffer = read_buffer; + /** + * @author fenris + */ + function read_stdin() { + return (new Promise(function (resolve, reject) { + var input_raw = ""; + process.stdin.setEncoding("utf8"); + process.stdin.on("readable", function () { + var chunk; + while ((chunk = process.stdin.read()) !== null) { + input_raw += chunk; + } + }); + process.stdin.on("end", function () { + resolve(input_raw); + }); + })); + } + file.read_stdin = read_stdin; + /** + * @author fenris + */ + function write(path, content, options) { + if (options === void 0) { options = {}; } + options = Object.assign({ + "encoding": "utf-8", + }, options); + var nm_fs = require("fs"); + return (new Promise(function (resolve, reject) { + nm_fs.writeFile(path, content, { + "encoding": options.encoding, + "flag": "w", + }, function (error) { + if (error == null) { + resolve(undefined); + } + else { + reject(error); + } + }); + })); + } + file.write = write; + /** + * @author fenris + */ + function write_buffer(path, content, options) { + if (options === void 0) { options = {}; } + options = Object.assign({}, options); + var nm_fs = require("fs"); + return (new Promise(function (resolve, reject) { + nm_fs.writeFile(path, content, { + "flag": "w", + }, function (error) { + if (error == null) { + resolve(undefined); + } + else { + reject(error); + } + }); + })); + } + file.write_buffer = write_buffer; + })(file = lib_plankton.file || (lib_plankton.file = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:object«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:object« 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:object« 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:object«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var object; + (function (object_1) { + /** + * @author fenris + */ + function fetch(object, fieldname, fallback, escalation) { + if (fallback === void 0) { fallback = null; } + if (escalation === void 0) { escalation = 1; } + if ((fieldname in object) && (object[fieldname] !== undefined)) { + return object[fieldname]; + } + else { + switch (escalation) { + case 0: { + return fallback; + break; + } + case 1: { + var message = ("field '".concat(fieldname, "' not in structure")); + message += ("; using fallback value '".concat(String(fallback), "'")); + // console.warn(message); + return fallback; + break; + } + case 2: { + var message = ("field '".concat(fieldname, "' not in structure")); + throw (new Error(message)); + break; + } + default: { + throw (new Error("invalid escalation level ".concat(escalation))); + break; + } + } + } + } + object_1.fetch = fetch; + /** + * @author fenris + */ + function map(object_from, transformator) { + var object_to = {}; + Object.keys(object_from).forEach(function (key) { return (object_to[key] = transformator(object_from[key], key)); }); + return object_to; + } + object_1.map = map; + /** + * @desc gibt ein Objekt mit bestimmten Einträgen des Eingabe-Objekts zurück + * @author fenris + */ + function filter(object_from, predicate) { + var object_to = {}; + Object.keys(object_from).forEach(function (key) { + var value = object_from[key]; + if (predicate(value, key)) { + object_to[key] = value; + } + }); + return object_to; + } + object_1.filter = filter; + /** + * @desc wandelt ein Array mit Einträgen der Form {key,value} in ein entsprechendes Objekt um + * @author fenris + */ + function from_array(array) { + var object = {}; + array.forEach(function (entry) { return (object[entry.key] = entry.value); }); + return object; + } + object_1.from_array = from_array; + /** + * @desc wandelt ein Objekt in ein entsprechendes Array mit Einträgen der Form {key,value} um + * @author fenris + */ + function to_array(object) { + var array = []; + Object.keys(object).forEach(function (key) { return array.push({ "key": key, "value": object[key] }); }); + return array; + } + object_1.to_array = to_array; + /** + * @desc gibt eine Liste von Schlüsseln eines Objekts zurück + * @author fenris + */ + function keys(object) { + return Object.keys(object); + } + object_1.keys = keys; + /** + * @desc gibt eine Liste von Werten eines Objekts zurück + * @author fenris + */ + function values(object) { + return to_array(object).map(function (entry) { return entry.value; }); + } + object_1.values = values; + /** + * @desc liest ein Baum-artiges Objekt an einer bestimmten Stelle aus + * @author fenris + */ + function path_read(object, path, fallback, escalation) { + if (fallback === void 0) { fallback = null; } + if (escalation === void 0) { escalation = 1; } + var steps = ((path.length == 0) ? [] : path.split(".")); + if (steps.length == 0) { + throw (new Error("empty path")); + } + else { + var position_1 = object; + var reachable = (position_1 != null) && steps.slice(0, steps.length - 1).every(function (step) { + position_1 = lib_plankton.object.fetch(position_1, step, null, 0); + return (position_1 != null); + }); + if (reachable) { + return lib_plankton.object.fetch(position_1, steps[steps.length - 1], fallback, escalation); + } + else { + return lib_plankton.object.fetch({}, "_dummy_", fallback, escalation); + } + } + } + object_1.path_read = path_read; + /** + * @desc schreibt einen Wert an eine bestimmte Stelle in einem Baum-artigen Objekt + * @author fenris + */ + function path_write(object, path, value, construct) { + if (construct === void 0) { construct = true; } + var steps = ((path.length == 0) ? [] : path.split(".")); + if (steps.length == 0) { + throw (new Error("empty path")); + } + else { + var position_2 = object; + var reachable = steps.slice(0, steps.length - 1).every(function (step) { + var position_ = lib_plankton.object.fetch(position_2, step, null, 0); + if (position_ == null) { + if (construct) { + position_2[step] = {}; + position_2 = position_2[step]; + return true; + } + else { + return false; + } + } + else { + position_2 = position_; + return true; + } + }); + if (reachable) { + position_2[steps[steps.length - 1]] = value; + } + else { + var message = ("path '".concat(path, "' does not exist and may not be constructed")); + throw (new Error(message)); + } + } + } + object_1.path_write = path_write; + /** + * @desc prüft ob ein Objekt einem bestimmten Muster entspricht + * @param {Object} object das zu prüfende Objekt + * @param {Object} pattern das einzuhaltende Muster + * @param {Function} connlate eine Funktion zum Feststellen der Gleichheit von Einzelwerten + * @author fenris + */ + function matches(object, pattern, collate) { + if (collate === void 0) { collate = instance_collate; } + return Object.keys(pattern).every(function (key) { return collate(pattern[key], object[key]); }); + } + object_1.matches = matches; + /** + * @desc erzeugt eine Projektion eines Baum-artigen Objekts in ein Listen-artiges Objekt + * @param {string} [separator] welches Zeichen als Trenner zwischen zwei Pfad-Schritten verwendet werden soll + * @author fenris + */ + function flatten(value, separator, key_for_element) { + if (separator === void 0) { separator = "."; } + if (key_for_element === void 0) { key_for_element = (function (index) { return ("element_" + index.toFixed(0)); }); } + var integrate = function (result, key_, value_) { + if (value_ == null) { + result[key_] = value_; + } + else { + // primitive Werte direkt übernehmen + if (typeof (value_) != "object") { + result[key_] = value_; + } + // sonst durch rekursiven Aufruf die flache Variante des Wertes ermitteln und einarbeiten + else { + var result_1 = flatten(value_); + Object.keys(result_1) + .forEach(function (key__) { + var value__ = result_1[key__]; + var key_new = (key_ + separator + key__); + result[key_new] = value__; + }); + } + } + }; + if ((value === null) || (value === undefined)) { + return null; + } + else { + var result_2 = {}; + if (typeof (value) != "object") { + result_2["value"] = value; + } + else { + if (value instanceof Array) { + var array = (value); + array + .forEach(function (element, index) { + integrate(result_2, key_for_element(index), element); + }); + } + else { + var object_2 = (value); + Object.keys(object_2) + .forEach(function (key) { + integrate(result_2, key, object_2[key]); + }); + } + } + return result_2; + } + } + object_1.flatten = flatten; + /** + * @author fenris + */ + function clash(x, y, _a) { + var _b = _a === void 0 ? {} : _a, _c = _b["overwrite"], overwrite = _c === void 0 ? true : _c, _d = _b["hooks"], _e = _d === void 0 ? {} : _d, _f = _e["existing"], hook_existing = _f === void 0 ? null : _f; + if (hook_existing == null) { + (function (key, value_old, value_new) { return console.warn("field ".concat(key, " already defined")); }); + } + var z = {}; + Object.keys(x).forEach(function (key) { + z[key] = x[key]; + }); + Object.keys(y).forEach(function (key) { + if (key in z) { + if (hook_existing != null) { + hook_existing(key, z[key], y[key]); + } + if (overwrite) { + z[key] = y[key]; + } + } + else { + z[key] = y[key]; + } + }); + return z; + } + object_1.clash = clash; + /** + * @author fenris + */ + function patch(core, mantle, deep, path) { + if (deep === void 0) { deep = true; } + if (path === void 0) { path = null; } + if (mantle == null) { + console.warn("mantle is null; core was", core); + } + else { + Object.keys(mantle).forEach(function (key) { + var path_ = ((path == null) ? key : "".concat(path, ".").concat(key)); + var value_mantle = mantle[key]; + if (!(key in core)) { + if ((typeof (value_mantle) == "object") && (value_mantle != null) && deep) { + if (value_mantle instanceof Array) { + core[key] = []; + value_mantle.forEach(function (element) { + if ((typeof (element) == "object") && (element != null)) { + var element_ = {}; + patch(element_, element); + core[key].push(element_); + } + else { + core[key].push(element); + } + }); + } + else { + core[key] = {}; + patch(core[key], value_mantle, deep, path_); + } + } + else { + core[key] = value_mantle; + } + } + else { + var value_core = core[key]; + if (typeof (value_core) == typeof (value_mantle)) { + if ((typeof (value_mantle) == "object") && (value_mantle != null) && deep) { + patch(core[key], value_mantle, deep, path_); + } + else { + core[key] = value_mantle; + } + } + else { + if ((value_core != null) && (value_mantle != null)) { + var message = "objects have different shapes at path '".concat(path_, "'; core has type '").concat(typeof (value_core), "' and mantle has type '").concat(typeof (value_mantle), "'"); + console.warn(message); + } + core[key] = value_mantle; + // throw (new Error(message)); + } + } + }); + } + } + object_1.patch = patch; + /** + * @author fenris + */ + function patched(core, mantle, deep) { + if (deep === void 0) { deep = undefined; } + var result = {}; + patch(result, core, deep); + patch(result, mantle, deep); + return result; + } + object_1.patched = patched; + /** + * @author fenris + */ + function attached(object, key, value) { + var mantle = {}; + mantle[key] = value; + return patched(object, mantle, false); + } + object_1.attached = attached; + /** + * @author fenris + */ + function copy(object) { + return patched({}, object); + } + object_1.copy = copy; + })(object = lib_plankton.object || (lib_plankton.object = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:call«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»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 . + */ +"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()); + }); +}; +/* +This file is part of »bacterio-plankton:call«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»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 . + */ +var lib_plankton; +(function (lib_plankton) { + var call; + (function (call) { + /** + * @desc hacked class for postfix function application + * @author fenris + */ + class class_valuewrapper { + /** + * @desc [constructor] + * @author fenris + */ + constructor(value) { + this.value = value; + } + /** + * @desc [accessor] applies a function and returns a new valuewrapper + * @author fenris + */ + pass(function_) { + return (new class_valuewrapper(function_(this.value))); + } + /** + * @desc [accessor] gives the wrapped value + * @author fenris + */ + extract() { + return this.value; + } + } + call.class_valuewrapper = class_valuewrapper; + /** + * @desc shortcut for constructing a valuewrapper-object + * @author fenris + */ + function vw(value) { + return (new class_valuewrapper(value)); + } + call.vw = vw; + /** + * @author fenris + */ + function use(input, function_) { + return function_(input); + } + call.use = use; + /** + * @desc just the identity; useful for some callbacks etc. + * @author fenris + */ + function id(x) { + return x; + } + call.id = id; + /** + * @desc 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, call.args2list(arguments))); + }); + } + call.compose = compose; + /** + * @desc transforms a function with sequential input into a function with leveled input; example: add(2,3) = curryfy(add)(2)(3) + * @param {function} f + * @param {int} n (don't set manually) + * @return {function} the currified version of the in put function + * @author fenris + */ + function curryfy(f, n = f.length) { + switch (n) { + case 0: { + throw (new Error("[curryfy] impossible")); + // break; + } + case 1: { + return f; + // break; + } + default: { + return (function (x) { + return (curryfy(function () { return f.apply(f, [x].concat(call.args2list(arguments))); }, n - 1)); + }); + // break; + } + } + } + call.curryfy = curryfy; + })(call = lib_plankton.call || (lib_plankton.call = {})); +})(lib_plankton || (lib_plankton = {})); +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(state); + } + else if (executors.length == 1) { + return executors[0](state); + } + else { + return ( + executor_chain( + 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(chain, current, deferred), + executor_resolve(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(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' + + +»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 . + */ +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 + */ + function promise_show(label) { + return (result => promise_make((resolve, reject) => { + // lib_plankton.log.info(label + ": " + instance_show(result)); + process.stdout.write(label + ": " + instance_show(result)); + resolve(result); + })); + } + call.promise_show = promise_show; + /** + * @author fenris + */ + function promise_log(result) { + return promise_show("log"); + } + call.promise_log = promise_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' + + +»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 . + */ +var lib_plankton; +(function (lib_plankton) { + var call; + (function (call) { + call.initializer_state_initial = 0; + call.initializer_state_waiting = 1; + call.initializer_state_successful = 2; + call.initializer_state_failed = 3; + /** + * @author fenris + */ + function initializer_make(fetcher) { + let subject = { + "fetcher": fetcher, + "state": call.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 call.initializer_state_successful: { + subject.queue.forEach(entry => entry.resolve(subject.result)); + break; + } + case call.initializer_state_failed: { + subject.queue.forEach(entry => entry.reject(subject.reason)); + break; + } + default: { + let message = `unhandled state ${subject.state}`; + throw (new Error(message)); + break; + } + } + } + /** + * @author fenris + */ + function initializer_reset(subject) { + subject.state = call.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 call.initializer_state_initial: { + subject.state = call.initializer_state_waiting; + return (call.promise_make((resolve, reject) => { + subject.queue.push({ "resolve": resolve, "reject": reject }); + subject.fetcher().then(result => { + subject.state = call.initializer_state_successful; + subject.result = result; + initializer_actuate(subject); + }, reason => { + subject.state = call.initializer_state_failed; + subject.reason = reason; + initializer_actuate(subject); + }); + })); + break; + } + case call.initializer_state_waiting: { + return (call.promise_make((resolve, reject) => { + subject.queue.push({ "resolve": resolve, "reject": reject }); + })); + break; + } + case call.initializer_state_successful: { + return (call.promise_resolve(subject.result)); + break; + } + case call.initializer_state_failed: { + return (call.promise_reject(subject.reason)); + break; + } + default: { + let message = `unhandled state ${subject.state}`; + throw (new Error(message)); + break; + } + } + } + call.initializer_get = initializer_get; + /** + * @author fenris + */ + function initializer_get_sync(subject) { + switch (subject.state) { + case call.initializer_state_successful: { + return subject.result; + break; + } + case call.initializer_state_failed: { + throw subject.reason; + break; + } + default: { + let message = `unhandled state ${subject.state}`; + throw (new Error(message)); + break; + } + } + } + /** + * @author fenris + */ + function initializer_set_sync(subject, result) { + switch (subject.state) { + case call.initializer_state_successful: { + subject.result = result; + break; + } + case call.initializer_state_failed: { + subject.state = call.initializer_state_successful; + subject.result = result; + break; + } + default: { + let message = `unhandled state ${subject.state}`; + throw (new Error(message)); + 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' + + +»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 . + */ +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} first a simple deferral + * @param {(value1 : type_value1)=>type_deferral} 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_maybe.make_nothing(), + "right": lib_maybe.make_nothing(), + }; + let finish = function () { + if (lib_maybe.is_just(object.left) + && + lib_maybe.is_just(object.right)) { + let result = { + "left": lib_maybe.cull(object.left), + "right": lib_maybe.cull(object.right), + }; + convey(result); + } + else { + // do nothing + } + }; + deferral_use(deferral_left, input, output_left => { + object.left = lib_maybe.make_just(output_left); + finish(); + }); + deferral_use(deferral_right, input, output_right => { + object.right = lib_maybe.make_just(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(result, current), + deferral_compose_serial, deferral_id())); + } + call.deferral_chain = deferral_chain; + /** + * @author fenris + */ + /* + export function deferral_bunch( + members : {[name : string] : type_deferral} + ) : type_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' + + +»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 . + */ +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' + + +»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 . + */ +var lib_plankton; +(function (lib_plankton) { + var call; + (function (call) { + /** + * @author fenris + */ + function timeout(function_, delay) { + return ( + /*window.*/ setTimeout(function_, delay)); + } + call.timeout = timeout; + /** + * @desc a definition for a value being "defined" + * @author neuc + */ + function is_def(obj, null_is_valid = false) { + return (!((typeof (obj) === "undefined") + || + (!null_is_valid && (obj === null)))); + } + call.is_def = is_def; + /** + * @desc 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, type = null, null_is_valid = false) { + if (is_def(value, null_is_valid) + && + (is_def(type) + ? ((typeof value === type) + || + ((value === null) + && + null_is_valid)) + : true)) { + return value; + } + else { + return default_value; + } + } + call.def_val = def_val; + ; + /** + * @desc just the empty function; useful for some callbacks etc. + * @author fenris + */ + function nothing() { + } + call.nothing = nothing; + /** + * @desc outputs + * @author fenris + */ + /* + export function output(...args : Array) : void { + lib_plankton.log.info.apply(lib_log, args); + } + */ + /** + * @desc 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; + /** + * @desc provides the call for an attribute of a class as a regular function + * @param {string} name the name of the attribute + * @return {*} + * @author fenris + */ + function attribute(name) { + return ((object) => object[name]); + } + call.attribute = attribute; + /** + * @desc provides a method of a class as a regular function + * @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(unival, handlers, fallback = null) { + if (unival.kind in handlers) { + let handler = handlers[unival.kind]; + return handler(unival.data); + } + else { + let message = ("unhandled kind '" + unival.kind + "'"); + if (fallback !== null) { + console.warn(message); + return fallback(unival); + } + 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()), seconds); + })); + } + 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 = {})); +/* +This file is part of »bacterio-plankton:translate«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:translate« 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:translate« 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:translate«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var translate; + (function (translate) { + /** + * @desc contains the sets of strings + * @author fenris + */ + var _packages = {}; + /** + * @desc specifies in which order the languages shall be queried; if getting a string from language #0 fails, the + * system tries to get it from language #1, and so on + * @author fenris + */ + var _order = []; + /** + * @desc whether to automatically promote the language of a newly added package + * @author fenris + */ + var _autopromote = false; + /** + * @desc the level of verbosity, specifiying how much output the system shall provide about its actions + * @author fenris + */ + translate._verbosity = 1; + /** + * @desc which initial string to use for log-outputs + * @author fenris + */ + var _logprefix = "[lib_translate]"; + /** + * @desc moves a language to the top of the order, making it the primary one + * @author fenris + */ + function promote(identifier) { + if (Object.keys(_packages).indexOf(identifier) < 0) { + if (translate._verbosity >= 1) { + console.warn(`${_logprefix} package '${identifier}' doesn't exist yet`); + } + } + let position = _order.indexOf(identifier); + if (position >= 0) { + if (translate._verbosity >= 2) { + console.info(`${_logprefix} '${identifier}' already in order; will promote it`); + } + _order.splice(position, 1); + } + _order.unshift(identifier); + if (translate._verbosity >= 2) { + console.info(`${_logprefix} order is now ${_order.toString()}`); + } + } + translate.promote = promote; + /** + * @desc adds a package to the sytem + * @author fenris + */ + function add(package_) { + let identifier = package_.meta.identifier; + if (identifier in _packages) { + if (translate._verbosity >= 1) { + console.warn(`${_logprefix} package '${identifier}' has already been added; will overwrite`); + } + } + else { + if (translate._verbosity >= 2) { + console.log(`${_logprefix} got package '${identifier}'`); + } + } + _packages[identifier] = package_; + if (_autopromote) { + promote(identifier); + } + } + translate.add = add; + /** + * @desc integrates a package to the system, i.e. creates a new one if none existed so far or merges with an existing one + * @author fenris + */ + function feed(package_) { + let identifier = package_.meta.identifier; + if (identifier in _packages) { + lib_plankton.object.patch(_packages[identifier].tree, package_.tree, true); + } + else { + if (translate._verbosity >= 2) { + console.info(`${_logprefix} package '${identifier}' didn't exist so far; will create it now`); + } + add(package_); + } + } + translate.feed = feed; + /** + * @desc tries to retrieve a translation for a specific package identifier + * @author fenris + */ + function fetch(identifier, path, args = {}) { + if (!(identifier in _packages)) { + if (translate._verbosity >= 1) { + console.warn(`${_logprefix} no package '${identifier}'`); + } + return (new class_nothing()); + } + else { + // let str : string = lib_plankton.object.path_read(_packages[identifier].tree, path); + let str = _packages[identifier].tree[path]; + if (str == undefined) { + if (translate._verbosity >= 1) { + console.warn(`${_logprefix} string '${path}' missing in package '${identifier}'`); + } + return (new class_nothing()); + } + else { + // resolve references + { + let regexp_reference = new RegExp("#\\(([\\w\\.]*)(?:\\?(\\w+)=(\\w+)(?:&(\\w+)=(\\w+))*)?\\)"); + while (true) { + let matching = regexp_reference.exec(str); + if (matching != null) { + let path_ = matching[1]; + let args_ = {}; + if (translate._verbosity >= 2) { + // console.info(`${_logprefix} found reference to '${path_}' with args ${JSON.stringify(args_)}`); + console.info(`${_logprefix} found reference to '${path_}'`); + } + // parse args + { + for (let index = 2; index <= matching.length - 1; index += 2) { + let id = matching[index + 0]; + let value = matching[index + 1]; + if (id != undefined) { + args_[id] = value; + } + } + } + // fetch referenced string + { + let result_ = fetch(identifier, path_, args_); + if (result_.is_just()) { + let front = str.slice(0, matching.index); + let back = str.slice(matching.index + matching[0].length); + str = (front + result_.cull() + back); + } + else { + return (new class_nothing()); + break; + } + } + } + else { + break; + } + } + } + // insert arguments + { + str = lib_plankton.string.coin(str, args); + } + return (new class_just(str)); + } + } + } + translate.fetch = fetch; + /** + * @desc retrieves a string by going through the order and trying to fetch it for the current entry + * @author fenris + */ + function get(path, args = {}, fallback = null) { + if (fallback == null) { + fallback = `{${path}}`; + } + if (translate._verbosity >= 2) { + console.info(`${_logprefix} getting translation for string '${path}' with arguments ${JSON.stringify(args)} …`); + } + let result = new class_nothing(); + let found = _order.some(identifier => { + if (translate._verbosity >= 2) { + console.info(`${_logprefix} trying package '${identifier}' …`); + } + let result_ = fetch(identifier, path, args); + if (result_.is_just()) { + result = result_; + return true; + } + else { + return false; + } + }); + if (found) { + let str = result.cull(); + if (translate._verbosity >= 3) { + console.info(`${_logprefix} found translation: '${str}'`); + } + return str; + } + else { + let str = fallback; + if (translate._verbosity >= 1) { + console.warn(`${_logprefix} no package provides a translation for string '${path}'; will use the fallback translation '${str}'`); + } + return str; + } + } + translate.get = get; + /** + * @author fenris + */ + function list() { + return lib_plankton.object.to_array(_packages).map(x => x.value.meta); + } + translate.list = list; + /** + * @author fenris + * @todo get rid of this; it's currenly needed only for the cdh-internal lib_completion + */ + function paths() { + return lib_plankton.object.keys(lib_plankton.object.flatten(_packages[_order[0]].tree)); + } + translate.paths = paths; + /** + * @author fenris + */ + function initialize_promise({ "logprefix": logprefix = undefined, "verbosity": verbosity = undefined, "packages": packages = [], "order": order = undefined, "autopromote": autopromote = undefined, } = {}) { + return (lib_plankton.call.promise_resolve(undefined) + // set variables + .then(_ => { + if (logprefix != undefined) + _logprefix = logprefix; + if (verbosity != undefined) + translate._verbosity = verbosity; + // _packages = {}; + if (order != undefined) + _order = order; + if (autopromote != undefined) + _autopromote = autopromote; + lib_plankton.call.promise_resolve(undefined); + }) + // feed + .then(_ => { + packages.forEach(feed); + lib_plankton.call.promise_resolve(undefined); + })); + } + translate.initialize_promise = initialize_promise; + /** + * @author fenris + */ + function initialize_executor(stuff) { + return lib_plankton.call.promise_to_executor(initialize_promise(stuff)); + } + translate.initialize_executor = initialize_executor; + /** + * @author fenris + */ + function initialize(stuff) { + return initialize_executor(stuff); + } + translate.initialize = initialize; + })(translate = lib_plankton.translate || (lib_plankton.translate = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:translate«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:translate« 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:translate« 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:translate«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var translate; + (function (translate) { + /** + * @author fenris + */ + function iso_639_1_to_iso_639_2(iso6391) { + let mapping = { + "af": "afr", + "ar": "ara", + "bg": "bul", + "cs": "ces", + "da": "dan", + "de": "deu", + "el": "ell", + "en": "eng", + "eo": "epo", + "es": "esp", + "fa": "fas", + "fi": "fin", + "fr": "fra", + "hi": "hin", + "hr": "hrv", + "hu": "hun", + "is": "isl", + "it": "ita", + "ja": "jpn", + "ko": "kor", + "nb": "nob", + "nl": "nld", + "nn": "nno", + "pt": "por", + "pl": "pol", + "ro": "ron", + "ru": "rus", + "sk": "slk", + "sv": "swe", + "zh": "zho", + }; + return mapping[iso6391]; + } + translate.iso_639_1_to_iso_639_2 = iso_639_1_to_iso_639_2; + /** + * @author fenris + */ + function stance(str) { + let regexp = new RegExp("^translate:(.*)$"); + let matching = regexp.exec(str); + if (matching != null) { + return translate.get(matching[1]); + } + else { + return str; + } + } + translate.stance = stance; + })(translate = lib_plankton.translate || (lib_plankton.translate = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:args«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:args« 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:args« 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:args«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var args; + (function (args) { + /** + */ + var enum_environment; + (function (enum_environment) { + enum_environment["cli"] = "cli"; + enum_environment["url"] = "url"; + })(enum_environment = args.enum_environment || (args.enum_environment = {})); + ; + /** + */ + var enum_kind; + (function (enum_kind) { + enum_kind["positional"] = "positional"; + enum_kind["volatile"] = "volatile"; + })(enum_kind = args.enum_kind || (args.enum_kind = {})); + ; + /** + */ + var enum_type; + (function (enum_type) { + enum_type["boolean"] = "boolean"; + enum_type["integer"] = "int"; + enum_type["float"] = "float"; + enum_type["string"] = "string"; + })(enum_type = args.enum_type || (args.enum_type = {})); + ; + /** + */ + var enum_mode; + (function (enum_mode) { + enum_mode["replace"] = "replace"; + enum_mode["accumulate"] = "accumulate"; + })(enum_mode = args.enum_mode || (args.enum_mode = {})); + ; + })(args = lib_plankton.args || (lib_plankton.args = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:args«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:args« 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:args« 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:args«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var args; + (function (args) { + /* + export enum_mode { + replace = "replace", + accumulate = "accumulate", + }; + */ + /** + * @author fenris + */ + var class_argument = /** @class */ (function () { + /** + * @author fenris + */ + function class_argument(_a) { + var name = _a["name"], _b = _a["type"], type = _b === void 0 ? args.enum_type.string : _b, _c = _a["kind"], kind = _c === void 0 ? args.enum_kind.positional : _c, _d = _a["mode"], mode = _d === void 0 ? args.enum_mode.replace : _d, _e = _a["default"], default_ = _e === void 0 ? null : _e, _f = _a["info"], info = _f === void 0 ? null : _f, _g = _a["parameters"], parameters = _g === void 0 ? {} : _g, _h = _a["hidden"], hidden = _h === void 0 ? false : _h; + this.name = name; + this.type = type; + this.kind = kind; + this.mode = mode; + this.default_ = default_; + this.info = info; + this.parameters = parameters; + this.hidden = hidden; + if (!this.check()) { + throw (new Error("invalid argument-setup")); + } + } + /** + * @author fenris + */ + class_argument.positional = function (_a) { + var name = _a["name"], _b = _a["type"], type = _b === void 0 ? args.enum_type.string : _b, _c = _a["mode"], mode = _c === void 0 ? args.enum_mode.replace : _c, _d = _a["default"], default_ = _d === void 0 ? null : _d, _e = _a["info"], info = _e === void 0 ? null : _e, _f = _a["hidden"], hidden = _f === void 0 ? false : _f, index = _a["index"]; + return (new class_argument({ + "name": name, + "kind": args.enum_kind.positional, + "type": type, + "mode": mode, + "default": default_, + "info": info, + "hidden": hidden, + "parameters": { + "index": index, + }, + })); + }; + /** + * @author fenris + */ + class_argument.volatile = function (_a) { + var name = _a["name"], _b = _a["type"], type = _b === void 0 ? args.enum_type.string : _b, _c = _a["mode"], mode = _c === void 0 ? args.enum_mode.replace : _c, _d = _a["default"], default_ = _d === void 0 ? null : _d, _e = _a["info"], info = _e === void 0 ? null : _e, _f = _a["hidden"], hidden = _f === void 0 ? false : _f, indicators_short = _a["indicators_short"], indicators_long = _a["indicators_long"]; + return (new class_argument({ + "name": name, + "kind": args.enum_kind.volatile, + "type": type, + "mode": mode, + "default": default_, + "info": info, + "hidden": hidden, + "parameters": { + "indicators_short": indicators_short, + "indicators_long": indicators_long, + }, + })); + }; + /** + * @author fenris + */ + class_argument.prototype.check = function () { + var _this = this; + return [ + function () { return ((!(_this.kind == args.enum_kind.volatile)) + || + (("indicators_long" in _this.parameters) + && + (_this.parameters["indicators_long"]["length"] >= 0))); }, + ].every(function (condition) { return condition(); }); + }; + /** + * @author fenris + */ + class_argument.prototype.name_get = function () { + return this.name; + }; + /** + * @author fenris + */ + class_argument.prototype.kind_get = function () { + return this.kind; + }; + /** + * @author fenris + */ + class_argument.prototype.type_get = function () { + return this.type; + }; + /** + * @author fenris + */ + class_argument.prototype.mode_get = function () { + return this.mode; + }; + /** + * @author fenris + */ + class_argument.prototype.default_get = function () { + return this.default_; + }; + /** + * @author fenris + */ + class_argument.prototype.parameters_get = function () { + return this.parameters; + }; + /** + * @author fenris + */ + class_argument.prototype.hidden_get = function () { + return this.hidden; + }; + /** + * @author fenris + */ + class_argument.prototype.toString = function () { + return "<".concat(this.name, ">"); + }; + /** + * @author fenris + */ + class_argument.prototype.indicator_main = function () { + if (this.kind === args.enum_kind.volatile) { + return this.parameters["indicators_long"][0]; + } + else { + return null; + } + }; + /** + * @author fenris + */ + class_argument.prototype.pattern_value = function () { + switch (this.type) { + case args.enum_type.boolean: { + return "false|true"; + break; + } + case args.enum_type.integer: { + return "[0-9]+"; + break; + } + case args.enum_type.float: { + return "\\d*(?:\\.\\d+)?"; + break; + } + case args.enum_type.string: { + return "\\S+"; + break; + } + default: { + throw (new Error("unhandled type ".concat(this.type))); + break; + } + } + }; + /** + * @author fenris + */ + class_argument.prototype.extract = function (raw) { + switch (this.type) { + case args.enum_type.boolean: { + return (raw != "false"); + break; + } + case args.enum_type.integer: { + return parseInt(raw); + break; + } + case args.enum_type.float: { + return parseFloat(raw); + break; + } + case args.enum_type.string: { + return raw; + break; + } + default: { + throw (new Error("unhandled type ".concat(this.type))); + break; + } + } + }; + /** + * @author fenris + */ + class_argument.prototype.assign = function (data, target, raw) { + var value = this.extract(raw); + switch (this.mode) { + case args.enum_mode.replace: { + data[target] = value; + break; + } + case args.enum_mode.accumulate: { + /* + if (! (this.name in data)) { + data[this.name] = []; + } + */ + data[target].push(value); + break; + } + default: { + throw (new Error("unhandled mode ".concat(this.mode))); + } + } + }; + /** + * @author fenris + */ + class_argument.prototype.make = function (data, target) { + var value = data[target]; + return value.toString(); + }; + /** + * @author fenris + */ + class_argument.prototype.generate_help = function () { + var _this = this; + var _a, _b, _c, _d; + var output = ""; + { + switch (this.kind) { + case args.enum_kind.positional: { + var line = ""; + line += "\t"; + line += "<".concat(this.name, ">"); + line += "\n"; + output += line; + } + case args.enum_kind.volatile: { + var line = ""; + line += "\t"; + if (this.type === args.enum_type.boolean) { + line += ([] + .concat(((_a = this.parameters["indicators_short"]) !== null && _a !== void 0 ? _a : []).map(function (indicator) { return ("-" + indicator); })) + .concat(((_b = this.parameters["indicators_long"]) !== null && _b !== void 0 ? _b : []).map(function (indicator) { return ("--" + indicator); })) + .join(" | ")); + } + else { + line += ([] + .concat(((_c = this.parameters["indicators_short"]) !== null && _c !== void 0 ? _c : []).map(function (indicator) { return ("-" + indicator + " " + ("<" + _this.name + ">")); })) + .concat(((_d = this.parameters["indicators_long"]) !== null && _d !== void 0 ? _d : []).map(function (indicator) { return ("--" + indicator + "=" + ("<" + _this.name + ">")); })) + .join(" | ")); + } + line += "\n"; + output += line; + } + } + } + { + var line = ""; + line += "\t\t"; + var infotext = ((this.info == null) ? "(no info available)" : this.info); + line += infotext; + if ((this.type != "boolean") && (this.default_ != null)) { + line += "; default: ".concat(this.default_.toString()); + } + line += "\n"; + output += line; + } + return output; + }; + return class_argument; + }()); + args.class_argument = class_argument; + })(args = lib_plankton.args || (lib_plankton.args = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:args«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:args« 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:args« 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:args«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var args; + (function (args) { + /** + * @author fenris + */ + var settings = { + "environment": { + "cli": { + "symbols": { + "delimiter": " ", + "prefix": "--", + "assignment": "=", + }, + }, + "url": { + "symbols": { + "delimiter": "&", + "prefix": "", + "assignment": "=", + } + } + }, + }; + /** + * @author fenris + */ + args.verbosity = 0; + /** + * @author fenris + * @todo check validity + */ + var class_handler = /** @class */ (function () { + /** + * @author fenris + */ + function class_handler(arguments_) { + this.arguments_ = arguments_; + } + /** + * @author fenris + */ + class_handler.prototype.filter = function (kind) { + var arguments_ = {}; + for (var _i = 0, _a = Object.entries(this.arguments_); _i < _a.length; _i++) { + var _b = _a[_i], name = _b[0], argument = _b[1]; + if (argument.kind_get() == kind) { + arguments_[name] = argument; + } + } + return arguments_; + }; + /** + * @author fenris + */ + class_handler.prototype.read = function (environment, input, data) { + var _this = this; + if (data === void 0) { data = {}; } + switch (environment) { + case args.enum_environment.cli: + case args.enum_environment.url: { + // default values + { + for (var _i = 0, _a = Object.entries(this.arguments_); _i < _a.length; _i++) { + var _b = _a[_i], name = _b[0], argument = _b[1]; + data[name] = argument.default_get(); + } + } + // preprocessing + { + // short indicators (lil hacky ...) + { + if (environment == args.enum_environment.cli) { + for (var _c = 0, _d = Object.entries(this.filter(args.enum_kind.volatile)); _c < _d.length; _c++) { + var _e = _d[_c], name = _e[0], argument = _e[1]; + // console.info(argument.parameters_get()["indicators_short"].join("|")); + var pattern_from = ""; + { + pattern_from += "(?:^|".concat(settings["environment"][environment]["symbols"]["delimiter"], ")"); + pattern_from += "-".concat(argument.parameters_get()["indicators_short"].join("|")); + pattern_from += "(?:$|".concat(settings["environment"][environment]["symbols"]["delimiter"], ")"); + } + var pattern_to = ""; + { + pattern_to += settings["environment"][environment]["symbols"]["delimiter"]; + pattern_to += settings["environment"][environment]["symbols"]["prefix"]; + pattern_to += argument.indicator_main(); + if (argument.type_get() == args.enum_type.boolean) { + pattern_to += settings["environment"][environment]["symbols"]["delimiter"]; + } + else { + pattern_to += settings["environment"][environment]["symbols"]["assignment"]; + } + } + var result = input.replace(new RegExp(pattern_from, "g"), pattern_to); + lib_plankton.log.debug("lib_args:read:replacing", { + "pattern_from": pattern_from, + "pattern_to": pattern_to, + "input": input, + "result": result, + }); + input = result; + } + } + } + lib_plankton.log.debug("lib_args:read:current_input", { + "input": input, + }); + } + // parsing + { + var parts = input + .split(settings["environment"][environment]["symbols"]["delimiter"]) + .filter(function (x) { return (x != ""); }); + var index_expected_1 = 0; + parts.forEach(function (part) { + lib_plankton.log.debug("lib_args:read:analyzing", { + "part": part, + }); + var found = [ + function () { + lib_plankton.log.debug("lib_args:read:probing_as_volatile", { + "part": part, + }); + for (var _i = 0, _a = Object.entries(_this.filter(args.enum_kind.volatile)); _i < _a.length; _i++) { + var _b = _a[_i], name = _b[0], argument = _b[1]; + lib_plankton.log.debug("lib_args:read:probing_as_volatile:trying", { + "part": part, + "argument": argument.toString(), + }); + var pattern = ""; + { + var pattern_front = ""; + pattern_front += "".concat(settings["environment"][environment]["symbols"]["prefix"]); + pattern_front += "(?:".concat(argument.parameters_get()["indicators_long"].join("|"), ")"); + pattern += pattern_front; + } + { + var pattern_back = ""; + pattern_back += "".concat(settings["environment"][environment]["symbols"]["assignment"]); + pattern_back += "(".concat(argument.pattern_value(), ")"); + if (argument.type_get() == args.enum_type.boolean) { + pattern_back = "(?:".concat(pattern_back, ")?"); + } + pattern += pattern_back; + } + lib_plankton.log.debug("lib_args:read:probing_as_volatile:pattern", { + "pattern": pattern, + }); + var regexp = new RegExp(pattern); + var matching = regexp.exec(part); + lib_plankton.log.debug("lib_args:read:probing_as_volatile:matching", { + "matching": matching, + }); + if (matching == null) { + // do nothing + } + else { + argument.assign(data, name, matching[1]); + return true; + } + } + return false; + }, + function () { + lib_plankton.log.debug("lib_args:read:probing_as_positional", { + "part": part, + }); + var positional = _this.filter(args.enum_kind.positional); + for (var _i = 0, _a = Object.entries(positional); _i < _a.length; _i++) { + var _b = _a[_i], name = _b[0], argument = _b[1]; + if (argument.parameters_get()['index'] !== index_expected_1) { + // do nothing + } + else { + lib_plankton.log.debug("lib_args:read:probing_as_positional:trying", { + "part": part, + "argument": argument.toString(), + }); + var pattern = ""; + { + var pattern_back = ""; + pattern_back += "(".concat(argument.pattern_value(), ")"); + pattern += pattern_back; + } + lib_plankton.log.debug("lib_args:read:probing_as_positional:pattern", { + "pattern": pattern, + }); + var regexp = new RegExp(pattern); + var matching = regexp.exec(part); + lib_plankton.log.debug("lib_args:read:probing_as_positional:matching", { + "matching": matching, + }); + if (matching == null) { + return false; + } + else { + argument.assign(data, name, matching[1]); + index_expected_1 += 1; + return true; + } + } + } + return false; + }, + ].some(function (x) { return x(); }); + if (!found) { + lib_plankton.log.warning("lib_args:read:could_not_parse", { + "part": part, + }); + } + }); + } + return data; + break; + } + default: { + throw (new Error("unhandled environment ".concat(environment))); + break; + } + } + }; + /** + * @author fenris + * @todo handle if the data object doesn't have the required field or the type is wrong or sth. + */ + class_handler.prototype.write = function (environment, data) { + switch (environment) { + case args.enum_environment.cli: { + return (([] + .concat(Object.entries(this.filter(args.enum_kind.volatile)).map(function (_a) { + var name = _a[0], argument = _a[1]; + var values; + switch (argument.mode_get()) { + case args.enum_mode.replace: { + values = [data[argument.name_get()]]; + break; + } + case args.enum_mode.accumulate: { + values = data[argument.name_get()]; + break; + } + } + return (values + .map(function (value) { return ((settings["environment"][environment]["symbols"]["prefix"] + + + argument.parameters_get()["indicators_long"][0]) + + + (settings["environment"][environment]["symbols"]["assignment"] + + + value.toString())); }) + .join(" ")); + })) + .concat(Object.entries(this.filter(args.enum_kind.positional)).map(function (_a) { + var name = _a[0], argument = _a[1]; + var raw = ""; + { + var raw_back = ""; + raw_back += argument.make(data, name); + raw += raw_back; + } + return raw; + }))) + .join(settings["environment"][environment]["symbols"]["delimiter"])); + break; + } + default: { + throw (new Error("unhandled environment ".concat(environment))); + break; + } + } + }; + /** + * @desc manpage-like info-sheet + * @author fenris + */ + class_handler.prototype.generate_help = function (_a) { + var _b = _a["programname"], programname = _b === void 0 ? null : _b, _c = _a["author"], author = _c === void 0 ? null : _c, _d = _a["description"], description = _d === void 0 ? null : _d, _e = _a["executable"], executable = _e === void 0 ? null : _e; + var environment = args.enum_environment.cli; + var output = ""; + { + var section = ""; + { + var line = ""; + line += ""; + line += "INFO"; + line += "\n"; + section += line; + } + { + var line = ""; + line += "\t"; + line += "".concat(programname, " -- ").concat(description); + line += "\n"; + section += line; + } + section += "\n"; + output += section; + } + { + if (author != null) { + var section = ""; + { + var line = ""; + line += ""; + line += "AUTHOR"; + line += "\n"; + section += line; + } + { + var line = ""; + line += "\t"; + line += "".concat(author); + line += "\n"; + section += line; + } + section += "\n"; + output += section; + } + } + { + var section = ""; + { + var line = ""; + line += ""; + line += "SYNOPSIS"; + line += "\n"; + section += line; + } + { + var line = ""; + line += "\t"; + line += executable; + line += settings["environment"][environment]["symbols"]["delimiter"]; + line += Object.entries(this.filter(args.enum_kind.positional)) + .map(function (_a) { + var name = _a[0], argument = _a[1]; + var part = ""; + part += "<".concat(argument.name_get(), ">"); + return part; + }) + .join(settings["environment"][environment]["symbols"]["delimiter"]); + line += settings["environment"][environment]["symbols"]["delimiter"]; + line += Object.entries(this.filter(args.enum_kind.volatile)) + .filter(function (_a) { + var name = _a[0], argument = _a[1]; + return (!argument.hidden_get()); + }) + .map(function (_a) { + var name = _a[0], argument = _a[1]; + var part = ""; + // part += settings["environment"][environment]["symbols"]["prefix"]; + part += "-"; + part += argument.parameters_get()["indicators_short"][0]; + if (argument.type_get() != "boolean") { + /* + part += settings["environment"][environment]["symbols"]["assignment"]; + part += `<${argument.name_get()}>`; + */ + part += " "; + part += "<".concat(argument.name_get(), ">"); + } + part = "[".concat(part, "]"); + return part; + }) + .join(settings["environment"][environment]["symbols"]["delimiter"]); + line += "\n"; + section += line; + } + section += "\n"; + output += section; + } + { + var section = ""; + { + var line = ""; + line += ""; + line += "OPTIONS"; + line += "\n"; + section += line; + } + { + section += (Object.entries(this.arguments_) + .filter(function (_a) { + var name = _a[0], argument = _a[1]; + return (!argument.hidden_get()); + }) + .map(function (_a) { + var name = _a[0], argument = _a[1]; + return argument.generate_help(); + }) + .join("\n")); + } + section += "\n"; + output += section; + } + return output; + }; + return class_handler; + }()); + args.class_handler = class_handler; + })(args = lib_plankton.args || (lib_plankton.args = {})); +})(lib_plankton || (lib_plankton = {})); diff --git a/source/localization/de.json b/source/localization/de.json index b845609..ba0fc67 100644 --- a/source/localization/de.json +++ b/source/localization/de.json @@ -12,6 +12,7 @@ "help.args.send_ok_notifications": "ob '{{condition_name}}'-Zustände gemeldet werden sollen", "help.args.language": "welche Sprache verwendet werden soll (statt der in den Umgebungs-Variablen gesetzten)", "help.args.erase_state": "ob der Zustand bei Start gelöscht werden soll; das hat zur Folge, dass alle Prüfungen unmittelbar durchgeführt werden", + "help.args.show_help": "nur die Hilfe zur Standard-Ausgabe schreiben und beenden", "help.args.show_schema": "nur das hmdl-JSON-Schema zur Standard-Ausgabe schreiben und beenden", "help.args.expose_full_order": "nur den Pfad zur Datenbank-Datei zur Standard-Ausgabe schreiben und beenden (nützlich für Fehlersuche)", "help.args.show_version": "nur die Version zur Standard-Ausgabe schreiben und beenden", diff --git a/source/localization/en.json b/source/localization/en.json index 2263d34..fa43aa6 100644 --- a/source/localization/en.json +++ b/source/localization/en.json @@ -12,6 +12,7 @@ "help.args.send_ok_notifications": "whether an '{{condition_name}}' condition shall be reported", "help.args.language": "language to use (instead of the language, set in the environment variables)", "help.args.erase_state": "whether the state shall be deleted on start; this will cause that all checks are executed immediatly", + "help.args.show_schema": "print help to stdout and exit", "help.args.show_schema": "print the hmdl JSON schema to stdout and exit", "help.args.expose_full_order": "only print the extended order to stdout and exit (useful for debugging)", "help.args.show_version": "only print the version to stdout and exit", diff --git a/source/logic/channels/_type.ts b/source/logic/channels/_type.ts new file mode 100644 index 0000000..27b3583 --- /dev/null +++ b/source/logic/channels/_type.ts @@ -0,0 +1,12 @@ +namespace _heimdall.channels +{ + + /** + */ + export type type_channel = { + parameters_schema : (() => _heimdall.helpers.json_schema.type_schema); + normalize_order_node : ((node : any) => any); + notify : (parameters, name, data, state, info) => Promise; + }; + +} diff --git a/source/logic/checks/_type.ts b/source/logic/checks/_type.ts new file mode 100644 index 0000000..b6c85aa --- /dev/null +++ b/source/logic/checks/_type.ts @@ -0,0 +1,12 @@ +namespace _heimdall.checks +{ + + /** + */ + export type type_check = { + parameters_schema : (() => _heimdall.helpers.json_schema.type_schema); + normalize_order_node : ((node : any) => any); + run : (parameters) => Promise<{condition : _heimdall.enum_condition; info : any;}>; + }; + +} diff --git a/source/logic/condition.ts b/source/logic/condition.ts new file mode 100644 index 0000000..a1000b6 --- /dev/null +++ b/source/logic/condition.ts @@ -0,0 +1,13 @@ +namespace _heimdall +{ + + /** + */ + export enum enum_condition { + unknown = 0, + ok = 1, + concerning = 2, + critical = 3, + }; + +} diff --git a/source/logic/helpers/json_schema.ts b/source/logic/helpers/json_schema.ts new file mode 100644 index 0000000..eb00171 --- /dev/null +++ b/source/logic/helpers/json_schema.ts @@ -0,0 +1,47 @@ +namespace _heimdall.helpers.json_schema +{ + + /** + */ + type type_type = ( + "null" + | + "boolean" + | + "integer" + | + "float" + | + "string" + | + "array" + | + "object" + ); + + + /** + */ + export type type_schema = { + type ?: ( + type_type + | + Array + ); + additionalProperties ?: ( + false + | + type_schema + ); + properties ?: Record; + required ?: Array; + description ?: string; + default ?: any; + minimum ?: int; + maximum ?: int; + enum ?: Array; + items ?: type_schema; + anyOf ?: Array; + }; + +} diff --git a/source/logic/main.ts b/source/logic/main.ts new file mode 100644 index 0000000..441dd35 --- /dev/null +++ b/source/logic/main.ts @@ -0,0 +1,237 @@ +async function main( +) : Promise +{ + // consts + const version : string = "0.8"; + + // init + await lib_plankton.translate.initialize_promise( + { + "verbosity": 1, + "order": ["de", "en"], + "packages": await Promise.all( + [ + {"identifier": "de", "path": "localization/de.json"}, + {"identifier": "en", "path": "localization/en.json"}, + ] + .map( + (entry) => ( + lib_plankton.file.read(entry.path) + .then(content => Promise.resolve(JSON.parse(content))) + .then(tree => Promise.resolve({"meta": {"identifier": entry.identifier}, "tree": tree})) + ) + ) + ), + } + ); + + // args + const arg_handler : lib_plankton.args.class_handler = new lib_plankton.args.class_handler( + { + "order_path": new lib_plankton.args.class_argument( + { + "name": "order_path", + "type": lib_plankton.args.enum_type.string, + "kind": lib_plankton.args.enum_kind.positional, + "mode": lib_plankton.args.enum_mode.replace, + "default": "monitoring.hmdl.json", + "parameters": { + "index": 0, + }, + "info": lib_plankton.translate.get("help.args.order_path"), + } + ), + "show_help": new lib_plankton.args.class_argument( + { + "name": "help", + "type": lib_plankton.args.enum_type.boolean, + "kind": lib_plankton.args.enum_kind.volatile, + "mode": lib_plankton.args.enum_mode.replace, + "default": false, + "parameters": { + "indicators_long": ["help"], + "indicators_short": ["h"], + }, + "info": lib_plankton.translate.get("help.args.show_help"), + } + ), + "show_version": new lib_plankton.args.class_argument( + { + "name": "version", + "type": lib_plankton.args.enum_type.boolean, + "kind": lib_plankton.args.enum_kind.volatile, + "mode": lib_plankton.args.enum_mode.replace, + "default": false, + "parameters": { + "indicators_long": ["version"], + "indicators_short": ["v"], + }, + "info": lib_plankton.translate.get("help.args.show_version"), + } + ), + "show_schema": new lib_plankton.args.class_argument( + { + "name": "schema", + "type": lib_plankton.args.enum_type.boolean, + "kind": lib_plankton.args.enum_kind.volatile, + "mode": lib_plankton.args.enum_mode.replace, + "default": false, + "parameters": { + "indicators_long": ["schema"], + "indicators_short": ["s"], + }, + "info": lib_plankton.translate.get("help.args.show_schema"), + } + ), + "expose_full_order": new lib_plankton.args.class_argument( + { + "name": "expose_full_order", + "type": lib_plankton.args.enum_type.boolean, + "kind": lib_plankton.args.enum_kind.volatile, + "mode": lib_plankton.args.enum_mode.replace, + "default": false, + "parameters": { + "indicators_long": ["expose-full-order"], + "indicators_short": ["e"], + }, + "info": lib_plankton.translate.get("help.args.expose_full_order"), + } + ), + "erase_state": new lib_plankton.args.class_argument( + { + "name": "erase_state", + "type": lib_plankton.args.enum_type.boolean, + "kind": lib_plankton.args.enum_kind.volatile, + "mode": lib_plankton.args.enum_mode.replace, + "default": false, + "parameters": { + "indicators_long": ["erase-state"], + "indicators_short": ["x"], + }, + "info": lib_plankton.translate.get("help.args.erase_state"), + } + ), + "database_path": new lib_plankton.args.class_argument( + { + "name": "database_path", + "type": lib_plankton.args.enum_type.string, + "kind": lib_plankton.args.enum_kind.volatile, + "mode": lib_plankton.args.enum_mode.replace, + "default": false, + "parameters": { + "indicators_long": ["database-path"], + "indicators_short": ["d"], + }, + "info": lib_plankton.translate.get("help.args.database_path"), + } + ), + "mutex_path": new lib_plankton.args.class_argument( + { + "name": "mutex_path", + "type": lib_plankton.args.enum_type.string, + "kind": lib_plankton.args.enum_kind.volatile, + "mode": lib_plankton.args.enum_mode.replace, + "default": false, + "parameters": { + "indicators_long": ["mutex-path"], + "indicators_short": ["m"], + }, + "info": lib_plankton.translate.get("help.args.mutex_path"), + } + ), + "send_ok_notifications": new lib_plankton.args.class_argument( + { + "name": "send_ok_notifications", + "type": lib_plankton.args.enum_type.boolean, + "kind": lib_plankton.args.enum_kind.volatile, + "mode": lib_plankton.args.enum_mode.replace, + "default": false, + "parameters": { + "indicators_long": ["send-ok-notifications"], + "indicators_short": ["y"], + }, + "info": lib_plankton.translate.get("help.args.send_ok_notifications"), + } + ), + "language": new lib_plankton.args.class_argument( + { + "name": "language", + "type": lib_plankton.args.enum_type.string, + "kind": lib_plankton.args.enum_kind.volatile, + "mode": lib_plankton.args.enum_mode.replace, + "default": false, + "parameters": { + "indicators_long": ["language"], + "indicators_short": ["l"], + }, + "info": lib_plankton.translate.get("help.args.language"), + } + ), + "time_to_live": new lib_plankton.args.class_argument( + { + "name": "time_to_live", + "type": lib_plankton.args.enum_type.float, + "kind": lib_plankton.args.enum_kind.volatile, + "mode": lib_plankton.args.enum_mode.replace, + "default": (60 * 60 * 24 * 7), + "parameters": { + "indicators_long": ["time-to-live"], + "indicators_short": ["t"], + }, + "info": lib_plankton.translate.get("help.args.time_to_live"), + } + ), + } + ); + const args : Record = arg_handler.read( + lib_plankton.args.enum_environment.cli, + process.argv.slice(2).join(" ") + ); + + // exec + if (args.show_help) { + process.stdout.write( + arg_handler.generate_help( + { + "programname": "heimdall", + "description": lib_plankton.translate.get("help.title"), + "executable": "heimdall", + } + ) + ); + } + else { + if (args.show_version) { + process.stdout.write(version + "\n"); + } + else { + if (args.show_version) { + process.stdout.write(version + "\n"); + } + else { + const check_kind_implementations : Record = { + }; + const channel_kind_implementations : Record = { + }; + if (args.show_schema) { + process.stdout.write( + lib_plankton.json.encode( + _heimdall.order.schema_root( + check_kind_implementations, + channel_kind_implementations + ), + true + ) + + + "\n" + ) + } + else { + process.stdout.write(JSON.stringify(args, undefined, "\t") + "\n"); + } + } + } + } +} + +main(); diff --git a/source/logic/order.ts b/source/logic/order.ts new file mode 100644 index 0000000..79b6c10 --- /dev/null +++ b/source/logic/order.ts @@ -0,0 +1,546 @@ +namespace _heimdall.order +{ + + function schema_active( + ) : _heimdall.helpers.json_schema.type_schema + { + return { + "description": "whether the check shall be executed", + "type": "boolean", + "default": true, + }; + } + + + function schema_threshold( + ) : _heimdall.helpers.json_schema.type_schema + { + return { + "description": "how often a condition has to occur in order to be reported", + "type": "integer", + "minimum": 1, + "default": 3, + }; + } + + + function schema_annoy( + ) : _heimdall.helpers.json_schema.type_schema + { + return { + "description": "whether notifications about non-ok states shall be kept sending after the threshold has been surpassed", + "type": "boolean", + "default": false, + }; + } + + + function schema_interval( + allow_null, + default_ + ) : _heimdall.helpers.json_schema.type_schema + { + return { + "anyOf": [ + { + "description": "in seconds", + "type": (allow_null ? "integer" : ["null", "integer"]), + "exclusiveMinimum": 0, + }, + { + "description": "as text", + "type": "string", + "enum": [ + "minute", + "hour", + "day", + "week", + ] + }, + ], + "default": default_, + }; + } + + + function schema_schedule( + ) + { + return { + "type": "object", + "additionalProperties": false, + "properties": { + "regular_interval": schema_interval(false, (60 * 60)), + "attentive_interval": schema_interval(false, (60 * 2)), + "reminding_interval": schema_interval(true, (60 * 60 * 24)), + }, + "required": [ + ], + }; + } + + + function schema_notifications( + channel_implementations : Record + ) + { + return { + "type": "array", + "items": { + "anyOf": ( + Object.entries(channel_implementations) + .map( + ([key, value]) => ({ + "title": ("notification channel '" + key + "'"), + "type": "object", + "unevaluatedProperties": false, + "properties": { + "kind": { + "type": "string", + "enum": [key] + }, + "parameters": value.parameters_schema(), + }, + "required": [ + "kind", + "parameters" + ], + }) + ) + ) + }, + "default": [ + { + "kind": "console", + "parameters": { + } + }, + ], + }; + } + + + export function schema_root( + check_kind_implementations : Record, + channel_implementations : Record, + ) + { + return { + "type": "object", + "additionalProperties": false, + "properties": { + "defaults": { + "description": "default values for checks", + "type": "object", + "additionalProperties": false, + "properties": { + "active": schema_active(), + "threshold": schema_threshold(), + "annoy": schema_annoy(), + "schedule": schema_schedule(), + "notifications": schema_notifications(channel_implementations), + }, + "required": [ + ], + }, + "includes": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "list of relative or absolute paths to other hmdl files on the local machine, which shall be subsumed in the overall monitoring task" + }, + "checks": { + "type": "array", + "items": { + "allOf": [ + { + "description": "should represent a specific check", + "type": "object", + "unevaluatedProperties": false, + "properties": { + "name": { + "type": "string" + }, + "title": { + "type": "string" + }, + "active": schema_active(), + "threshold": schema_threshold(), + "annoy": schema_annoy(), + "schedule": schema_schedule(), + "notifications": schema_notifications(channel_implementations), + }, + "required": [ + "name", + ], + }, + { + "anyOf": ( + Object.entries(check_kind_implementations) + .map( + ([key, value]) => ({ + "title": ("check '" + key + "'"), + "type": "object", + "unevaluatedProperties": false, + "properties": { + "kind": { + "type": "string", + "enum": [key] + }, + "parameters": value.parameters_schema(), + "custom": { + "description": "custom data, which shall be attached to notifications", + "default": null, + }, + }, + "required": [ + "kind", + "parameters", + ] + }) + ) + ), + }, + ] + } + } + }, + "required": [ + ] + }; + } + + + function normalize_interval( + interval_raw + ) + { + if (interval_raw === null) { + return null; + } + else { + if (typeof(interval_raw) === "number") { + return interval_raw; + } + else if (typeof(interval_raw) === "string") { + const map_ = { + "minute": (60), + "hour": (60 * 60), + "day": (60 * 60 * 24), + "week": (60 * 60 * 24 * 7), + }; + if (! (interval_raw in map_)) { + throw new Error("invalid string interval value: " + interval_raw); + } + else { + return map_[interval_raw]; + } + } + else { + throw new Error("invalid type for interval value"); + } + } + } + + + function normalize_schedule( + node + ) + { + const node_ = Object.assign( + { + "regular_interval": (60 * 60), + "attentive_interval": (60 * 2), + "reminding_interval": (60 * 60 * 24), + }, + node + ); + return { + "regular_interval": normalize_interval(node_["regular_interval"]), + "attentive_interval": normalize_interval(node_["attentive_interval"]), + "reminding_interval": normalize_interval(node_["reminding_interval"]), + }; + } + + + function normalize_notification( + channel_implementations : Record, + node + ) + { + if (! (node["kind"] in channel_implementations)) { + throw new Error("invalid notification kind: " + node["kind"]); + } + else { + return { + "kind": node["kind"], + "parameters": channel_implementations[node["kind"]].normalize_order_node(node["parameters"]), + }; + } + } + + + function normalize_defaults( + channel_implementations : Record, + node + ) + { + const node_ = Object.assign( + { + "active": true, + "threshold": 3, + "annoy": false, + "schedule": { + "regular_interval": (60 * 60), + "attentive_interval": (60 * 2), + "reminding_interval": (60 * 60 * 24), + }, + "notifications": [ + ], + }, + node + ) + return { + "active": node_["active"], + "threshold": node_["threshold"], + "annoy": node_["annoy"], + "schedule": node_["schedule"], + "notifications": ( + node_["notifications"] + .map(x => normalize_notification(channel_implementations, x)) + ), + }; + } + + + function normalize_check( + check_kind_implementations : Record, + channel_implementations : Record, + defaults, + node + ) + { + if (! ("name" in node)) { + throw new Error("missing mandatory field in 'check' node: 'name'"); + } + else { + if (! ("kind" in node)) { + throw new Error("missing mandatory field in 'check' node: 'kind'"); + } + else { + if (! (node["kind"] in check_kind_implementations)) { + throw new Error("invalid check kind: " + node["kind"]); + } + else { + const node_ = Object.assign( + Object.assign( + defaults, + { + "title": node["name"], + "parameters": {}, + "custom": null, + }, + ), + node + ); + let node__ = {}; + if (true) { + node__["name"] = node_["name"]; + } + if (true) { + node__["title"] = node_["title"]; + } + if ("active" in node_) { + node__["active"] = node_["active"]; + } + if ("threshold" in node_) { + node__["threshold"] = node_["threshold"]; + } + if ("annoy" in node_) { + node__["annoy"] = node_["annoy"]; + } + if ("schedule" in node_) { + node__["schedule"] = normalize_schedule(node_["schedule"]); + } + if ("notifications" in node_) { + node__["notifications"] = ( + node_["notifications"] + .map( + x => normalize_notification(channel_implementations, x), + ) + ); + } + if ("kind" in node_) { + node__["kind"] = node_["kind"]; + } + if (true) { + node__["parameters"] = check_kind_implementations[node_["kind"]].normalize_order_node(node_["parameters"]); + } + if ("custom" in node_) { + node__["custom"] = node_["custom"]; + } + return node__; + } + } + } + } + + + function normalize_root( + check_kind_implementations : Record, + channel_implementations : Record, + node, + options = {} + ) + { + options = Object.assign( + { + "use_implicit_default_values": true, + }, + options + ) + let counts = {}; + let checks_raw = ( + ("checks" in node) + ? node["checks"] + : [] + ); + checks_raw.forEach( + node_ => { + if (! (node_["name"] in counts)) { + counts[node_["name"]] = 0; + } + counts[node_["name"]] += 1; + } + ); + let fails : Array<[string, int]> = ( + Object.entries(counts) + .filter( + ([key, value]) => (value > 1) + ) + ); + if (fails.length > 0) { + throw new Error( + lib_plankton.string.coin( + "ambiguous check names: {{names}}", + { + "names": fails.map(([key, value]) => key).join(","), + } + ) + ); + } + else { + let defaults_raw = ( + ("defaults" in node) + ? node["defaults"] + : {} + ) + let defaults = ( + options["use_implicit_default_values"] + ? normalize_defaults( + channel_implementations, + defaults_raw + ) + : defaults_raw + ) + let includes = ( + ("includes" in node) + ? node["includes"] + : [] + ) + return { + "defaults": defaults, + "includes": includes, + "checks": ( + checks_raw + .map( + node_ => normalize_check( + check_kind_implementations, + channel_implementations, + defaults, + node_ + ) + ) + ) + }; + } + } + + + export async function load( + check_kind_implementations : Record, + channel_implementations : Record, + path : string, + options = {} + ) + { + options = Object.assign( + { + "root": true, + "already_included": new Set([]), + }, + options + ) + if (path in options["already_included"]) { + throw new Error("circular dependency detected") + } + else { + const order_raw = lib_plankton.json.decode(await lib_plankton.file.read(path)); + let includes : Array = ( + ("includes" in order_raw) + ? order_raw["includes"] + : [] + ); + for (let index = 0; index < includes.length; index += 1) { + let path_ = includes[index]; + let sub_order = load( + check_kind_implementations, + channel_implementations, + ( + _os.path.isabs(path_) + ? path_ + : _os.path.join(_os.path.dirname(path), path_) + ), + { + "root": false, + // TODO set union + "already_included": (options["already_included"] | {path}) + } + ) + if (! ("checks" in order_raw)) { + order_raw["checks"] = []; + } + order_raw["checks"].extend( + sub_order["checks"] + .map( + check => Object.assign( + check, + { + "name": lib_plankton.string.coin( + "{{prefix}}.{{original_name}}", + { + "prefix": _os.path.basename(path_).split(".")[0], + "original_name": check["name"], + } + ), + } + ), + sub_order["checks"] + ) + ); + order_raw["includes"] = []; + } + return normalize_root( + check_kind_implementations, + channel_implementations, + order_raw, + { + "use_implicit_default_values": options["root"], + } + ); + } + } + +} diff --git a/source/misc/head.js b/source/misc/head.js new file mode 100644 index 0000000..908ba84 --- /dev/null +++ b/source/misc/head.js @@ -0,0 +1 @@ +#!/usr/bin/env node diff --git a/tools/build b/tools/build index 6ac894d..c6127e7 100755 --- a/tools/build +++ b/tools/build @@ -1,136 +1,13 @@ -#!/usr/bin/env python3 +#!/usr/bin/env sh -import sys as _sys -import os as _os -import json as _json -import stat as _stat -import argparse as _argparse +## vars + +path_prj_from=tools/heimdall.prj.json +path_prj_to=heimdall.prj.json -def file_read(path): - handle = open(path, "r") - content = handle.read() - handle.close() - return content - +## exec -def file_write(path, content): - handle = open(path, "w") - handle.write(content) - handle.close() - - -def string_coin(template, arguments): - result = template - for (key, value, ) in arguments.items(): - result = result.replace("{{%s}}" % key, value) - return result - - -def python_data_encode(data): - return _json.dumps(data, indent = "\t") - - -def main(): - ## consts - dir_source = "source" - dir_build = "build" - sources_common = [ - _os.path.join(dir_source, "logic", "packages.py"), - _os.path.join(dir_source, "logic", "lib.py"), - _os.path.join(dir_source, "logic", "localization.py"), - _os.path.join(dir_source, "logic", "condition.py"), - _os.path.join(dir_source, "logic", "order.py"), - _os.path.join(dir_source, "logic", "checks", "_interface.py"), - _os.path.join(dir_source, "logic", "checks", "script.py"), - _os.path.join(dir_source, "logic", "checks", "file_state.py"), - _os.path.join(dir_source, "logic", "checks", "tls_certificate.py"), - _os.path.join(dir_source, "logic", "checks", "http_request.py"), - _os.path.join(dir_source, "logic", "checks", "generic_remote.py"), - _os.path.join(dir_source, "logic", "channels", "_interface.py"), - _os.path.join(dir_source, "logic", "channels", "console.py"), - _os.path.join(dir_source, "logic", "channels", "email.py"), - _os.path.join(dir_source, "logic", "channels", "libnotify.py"), - ] - targets = { - "app": { - "sources": ( - sources_common - + - [ - _os.path.join(dir_source, "logic", "main.py"), - ] - ), - "build": _os.path.join(dir_build, "heimdall"), - }, - "test": { - "sources": ( - sources_common - + - [ - _os.path.join(dir_source, "test", "test.py"), - ] - ), - "build": _os.path.join(dir_build, "heimdall-test"), - }, - } - - ## args - argument_parser = _argparse.ArgumentParser( - ) - argument_parser.add_argument( - "-t", - "--target", - type = str, - choices = ["app", "test"], - default = "app", - dest = "target_name", - help = "which target to build", - ) - args = argument_parser.parse_args() - - ## exec - if (not _os.path.exists(dir_build)): - _os.mkdir(dir_build) - - compilation = "" - compilation += "#!/usr/bin/env python3\n\n" - - ### localization - if True: - localization_data = dict( - map( - lambda entry: ( - entry.name.split(".")[0], - _json.loads(file_read(entry.path)), - ), - filter( - lambda entry: (entry.is_file() and entry.name.endswith(".json")), - _os.scandir(_os.path.join(dir_source, "localization")) - ) - ) - ) - compilation += string_coin( - "localization_data = {{data}}\n\n", - { - "data": python_data_encode(localization_data), - } - ) - - ### logic - for path in targets[args.target_name]["sources"]: - compilation += (file_read(path) + "\n") - - ### write to file - if _os.path.exists(targets[args.target_name]["build"]): - _os.remove(targets[args.target_name]["build"]) - file_write(targets[args.target_name]["build"], compilation) - - ### postproess - _os.chmod( - targets[args.target_name]["build"], - (_stat.S_IRWXU | _stat.S_IXGRP | _stat.S_IXOTH) - ) - - -main() +cp ${path_prj_from} ${path_prj_to} +koralle --execute ${path_prj_to} +rm ${path_prj_to} diff --git a/tools/heimdall.prj.json b/tools/heimdall.prj.json new file mode 100644 index 0000000..6106e61 --- /dev/null +++ b/tools/heimdall.prj.json @@ -0,0 +1,68 @@ +{ + "name": "heimdall", + "version": "0.8", + "dependencies": [ + ], + "roottask": { + "name": "logic", + "type": "group", + "sub": [ + { + "name": "postprocess", + "sub": [ + { + "name": "link", + "sub": [ + { + "name": "compile", + "type": "typescript", + "parameters": { + "inputs": [ + "lib/plankton/plankton.d.ts", + "source/logic/condition.ts", + "source/logic/helpers/json_schema.ts", + "source/logic/checks/_type.ts", + "source/logic/channels/_type.ts", + "source/logic/order.ts", + "source/logic/main.ts" + ], + "target": "es2020", + "output": "temp/heimdall-unlinked" + } + } + ], + "type": "concat", + "parameters": { + "inputs": [ + "source/misc/head.js", + "lib/plankton/plankton.js", + "temp/heimdall-unlinked" + ], + "output": "temp/heimdall-raw" + } + } + ], + "type": "script", + "parameters": { + "path": "tools/postprocess", + "interpreter": null, + "inputs": [ + "temp/heimdall-raw" + ], + "outputs": [ + "build/heimdall" + ] + } + }, + { + "name": "localization", + "type": "copy", + "parameters": { + "folder": true, + "input": "source/localization/", + "output": "build/localization/" + } + } + ] + } +} diff --git a/tools/makefile b/tools/makefile new file mode 100644 index 0000000..3b1d70c --- /dev/null +++ b/tools/makefile @@ -0,0 +1,14 @@ +## consts + +dir_lib := lib +dir_source := source +dir_build := build + +cmd_mkdir := mkdir -p +cmd_tsc := tsc +cmd_chmod := chmod + + +## rules + +${dir_build} diff --git a/tools/postprocess b/tools/postprocess new file mode 100755 index 0000000..434ede3 --- /dev/null +++ b/tools/postprocess @@ -0,0 +1,7 @@ +#!/usr/bin/env sh + +path_input=$1 +path_output=$2 + +cp ${path_input} ${path_output} +chmod +x ${path_output} diff --git a/tools/update-plankton b/tools/update-plankton new file mode 100755 index 0000000..655223f --- /dev/null +++ b/tools/update-plankton @@ -0,0 +1,23 @@ +#!/usr/bin/env sh + +## consts + +dir_lib=lib +dir_plankton=${dir_lib}/plankton + + +## vars + +modules="" +modules="${modules} string" +modules="${modules} json" +modules="${modules} file" +modules="${modules} translate" +modules="${modules} args" + + +## exec + +mkdir -p ${dir_plankton} +cd ${dir_plankton} +ptk bundle node ${modules}