From a975fa98a03aafc86afa9dc959e8997c4ffefa95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fra=C3=9F?= Date: Thu, 24 Apr 2025 22:48:05 +0000 Subject: [PATCH] [ini] --- .gitignore | 3 + libs/plankton/plankton.d.ts | 2828 +++++++++ libs/plankton/plankton.js | 8590 ++++++++++++++++++++++++++++ source/conf.ts | 149 + source/main.ts | 164 + source/sources/_functions.ts | 28 + source/sources/kalender_digital.ts | 92 + source/types.ts | 29 + tools/build | 16 + tools/clear | 5 + tools/deploy | 18 + tools/makefile | 40 + tools/update-plankton | 23 + 13 files changed, 11985 insertions(+) create mode 100644 .gitignore create mode 100644 libs/plankton/plankton.d.ts create mode 100644 libs/plankton/plankton.js create mode 100644 source/conf.ts create mode 100644 source/main.ts create mode 100644 source/sources/_functions.ts create mode 100644 source/sources/kalender_digital.ts create mode 100644 source/types.ts create mode 100755 tools/build create mode 100755 tools/clear create mode 100755 tools/deploy create mode 100644 tools/makefile create mode 100755 tools/update-plankton diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..82389ca --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/build/ +/temp/ +/conf/ diff --git a/libs/plankton/plankton.d.ts b/libs/plankton/plankton.d.ts new file mode 100644 index 0000000..9fb4ec3 --- /dev/null +++ b/libs/plankton/plankton.d.ts @@ -0,0 +1,2828 @@ +/** + * @author fenris + */ +type int = number; +/** + * @author fenris + */ +type float = number; +declare var process: any; +declare var require: any; +declare class Buffer { + constructor(x: string, modifier?: string); + static from(x: string, encoding?: string): any; + 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 + */ +/** + * @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): float; + /** + */ + function object_merge(core: Record, mantle: Record): Record; + /** + */ + function buffer_show(buffer: Buffer, { "block_size": option_block_size, "break_char": option_break_char, }?: { + block_size?: int; + break_char?: string; + }): string; +} +declare module lib_plankton.pod { + /** + * @author fenris + */ + type type_pod = { + kind: ("empty" | "filled"); + value?: type_value; + }; + /** + * @author fenris + */ + function make_empty(): type_pod; + /** + * @author fenris + */ + function make_filled(value: type_value): type_pod; + /** + * whether the pod is filled + * + * @author fenris + */ + function is_filled(pod: type_pod): boolean; + /** + * return the value, stored in the pod-wrapper + * + * @author fenris + */ + function cull(pod: type_pod): type_value; + /** + * to pass on a empty-pod or to use a filled-pod + * + * @author fenris + */ + function propagate(pod: type_pod, function_: ((value: type_value) => type_value_)): type_pod; + /** + * @author fenris + */ + function distinguish(pod: type_pod, function_empty: (() => type_result), function_filled: ((value: type_value) => type_result)): type_result; + /** + */ + function show(pod: type_pod, options?: { + show_value?: ((value: type_value) => string); + }): string; +} +declare module lib_plankton.pod { + /** + */ + class class_pod { + private subject; + constructor(subject: type_pod); + tear(): type_pod; + static empty(): class_pod; + static filled(value: type_value): class_pod; + is_empty(): boolean; + is_filled(): boolean; + cull(): type_value; + show(show_value?: any): string; + toString(): string; + propagate(function_: ((value: type_value) => type_value_)): class_pod; + distinguish(function_empty: (() => type_result), function_filled: ((value: type_value) => type_result)): type_result; + } +} +/** + * might be completely obsolete + */ +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: Record type_promise)>, options?: { + serial?: boolean; + }): type_promise, 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 + */ + /** + * @author fenris + */ + /** + * @author fenris + */ + function promise_attach(state: Record, promise: type_promise, name: string): type_promise, type_reason>; + /** + * @author fenris + */ + function promise_delay(promise: type_promise, delay: int): type_promise; +} +/** + * initializer might be obsolete, since promises are reusable after having been resolved or rejected + */ +declare namespace lib_plankton.call { + /** + * @author fenris + */ + enum enum_initializer_state { + initial = 0, + waiting = 1, + successful = 2, + failed = 3 + } + /** + * @author fenris + */ + type type_initializer = { + fetcher: (() => type_promise); + state?: enum_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): enum_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 { + /** + * converts the "arguments"-map into an array + * + * @param {Object} args + * @author fenris + */ + export function args2list(args: any): Array; + /** + * just the empty function; useful for some callbacks etc. + * + * @author fenris + */ + export function nothing(): void; + /** + * just the identity; useful for some callbacks etc.; defined as function instead of const for using type parameters + * + * @author fenris + */ + export function id(x: type_value): type_value; + /** + * just the identity; useful for some callbacks etc. + * + * @author fenris + */ + export function const_(x: type_value): ((y: any) => type_value); + /** + * 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 + */ + export function compose(function_f: ((type_x: any) => type_y), function_g: ((type_y: any) => type_z)): ((value: type_x) => type_z); + /** + * transforms a function with sequential input to a function with leveled input; example: add(2,3) = curryfy(add)(2)(3) + * + * @param {function} f + * @return {function} the currified version of the in put function + * @author fenris + */ + export function curryfy(f: Function): Function; + /** + * @author fenris + */ + export function convey(value: any, functions: Array): any; + /** + */ + class class_value_wrapper { + /** + */ + private value; + /** + */ + constructor(value: type_value); + /** + */ + convey(function_: ((value: type_value) => type_value_result)): class_value_wrapper; + /** + */ + cull(): type_value; + } + /** + */ + export function wrap(value: type_value): class_value_wrapper; + /** + * @author fenris + */ + export function timeout(procedure: (() => void), delay_in_seconds: float): int; + /** + * Promise version of "setTimeout" + * + * @author fenris + */ + export function defer(seconds: float, action: (() => type_result)): Promise; + /** + * a definition for a value being "defined" + * + * @author neuc + */ + export function is_def(obj: type_value, options?: { + null_is_valid?: boolean; + }): boolean; + /** + * returns the value if set and, when a type is specified, if the type is correct, if not return default_value + * + * @author neuc + */ + export function def_val(value: any, default_value: any, options?: { + type?: (null | string); + null_is_valid?: boolean; + }): any; + /** + * provides the call for an attribute of a class as a regular function; useful for processing lists of objects + * + * @param {string} name the name of the attribute + * @return {function} + * @author fenris + */ + export function attribute(name: string): ((object: type_object) => type_attribute); + /** + * provides a method of a class as a regular function; useful for processing lists of objects + * + * @param {string} name the name of the method + * @return {function} + * @author fenris + */ + export function method(name: string): ((object: type_object) => type_output); + /** + * @author fenris + */ + export type type_coproduct = { + kind: string; + data?: any; + }; + /** + * @author fenris + */ + export function distinguish(coproduct: type_coproduct, handlers: Record type_output)>, options?: { + fallback?: (null | ((coproduct?: type_coproduct) => type_output)); + }): type_output; + /** + */ + export function try_catch_wrap(get_value: (() => type_value)): { + value: (null | type_value); + error: (null | any); + }; + /** + */ + export function try_catch_wrap_async(get_value: (() => Promise)): Promise<{ + value: (null | type_value); + error: (null | any); + }>; + export {}; +} +declare namespace lib_plankton.email { + /** + */ + function send(smtp_credentials: { + host: string; + port: int; + username: string; + password: string; + }, sender: string, receivers: Array, subject: string, content: string): Promise; +} +declare namespace lib_plankton.log { + /** + */ + enum enum_level { + debug = 0, + info = 1, + notice = 2, + warning = 3, + error = 4 + } + /** + */ + type type_entry = { + level: enum_level; + incident: string; + tags: Array; + details: any; + }; + /** + */ + type type_channel_description = lib_plankton.call.type_coproduct; + /** + */ + type type_channel_logic = { + send: ((entry: type_entry) => void); + }; + /** + */ + type type_logger_data = Array; + /** + */ + type type_logger_logic = Array; + /** + */ + type type_format_definition = ({ + kind: "jsonl"; + data: { + structured: boolean; + }; + } | { + kind: "human_readable"; + data: {}; + }); +} +declare namespace lib_plankton.log { + /** + */ + function level_order(level1: enum_level, level2: enum_level): boolean; + /** + */ + function level_show(level: enum_level, { "abbreviated": option_abbreviated, }?: { + abbreviated?: boolean; + }): string; + /** + */ + function level_decode(level_string: string): enum_level; +} +declare namespace lib_plankton.log { + /** + * @todo use label + */ + function get_logger_logic(logger_data: type_logger_data): type_logger_logic; + /** + */ + function format_entry(format_definition: type_format_definition, entry: type_entry): string; + /** + */ + function parse_format_definition(format_definition_raw: any): type_format_definition; +} +declare namespace lib_plankton.log.channel.filtered { + /** + */ + type type_predicate = ((entry: type_entry) => boolean); + /** + */ + type type_subject = { + /** + * @todo check if it has to be logic + */ + core: type_channel_logic; + predicate: type_predicate; + }; + /** + */ + function predicate_incident(substring: string): type_predicate; + /** + */ + function predicate_level(threshold: enum_level): type_predicate; + /** + */ + function predicate_tag(tag: string): type_predicate; + /** + * combines other predicates in disjunctive normal form + */ + function predicate_complex(definition: Array>): type_predicate; + /** + */ + function send(subject: type_subject, entry: type_entry): void; + /** + */ + function logic(subject: type_subject): type_channel_logic; +} +declare namespace lib_plankton.log.channel.minlevel { + /** + */ + type type_subject = { + /** + * @todo check if it has to be logic + */ + core: type_channel_logic; + threshold: enum_level; + }; + /** + */ + function send(subject: type_subject, entry: type_entry): void; + /** + */ + function logic(subject: type_subject): type_channel_logic; +} +declare namespace lib_plankton.log.channel.std { + /** + */ + type type_subject = { + target: ("stdout" | "stderr"); + format: type_format_definition; + }; + /** + */ + function send(subject: type_subject, entry: type_entry): void; + /** + */ + function logic(subject: type_subject): type_channel_logic; +} +declare namespace lib_plankton.log.channel.file { + /** + */ + type type_subject = { + path: string; + format: type_format_definition; + }; + /** + */ + function send(subject: type_subject, entry: type_entry): void; + /** + */ + function logic(subject: type_subject): type_channel_logic; +} +declare namespace lib_plankton.log.channel.notify { + /** + */ + type type_subject = {}; + /** + * @todo tags + */ + function send(subject: type_subject, entry: type_entry): void; + /** + */ + function logic(subject: type_subject): type_channel_logic; +} +declare namespace lib_plankton.log.channel.email { + /** + */ + type type_subject = { + smtp_credentials: { + host: string; + port: int; + username: string; + password: string; + }; + sender: string; + receivers: Array; + }; + /** + * @todo tags + */ + function send(subject: type_subject, entry: type_entry): void; + /** + */ + function logic(subject: type_subject): type_channel_logic; +} +declare namespace lib_plankton.log { + /** + */ + function get_channel_logic(channel_description: type_channel_description): type_channel_logic; +} +declare namespace lib_plankton.log { + /** + */ + function default_logger(): type_logger_data; +} +declare namespace lib_plankton.log { + /** + */ + function set_main_logger(logger_data: type_logger_data): void; + /** + * consumes a log entry, i.e. sends it to all channels + */ + function send_(logger: type_logger_logic, entry: type_entry): void; + /** + * [convenience] + * + * @todo rename to "send" + */ + function debug_(logger: type_logger_logic, incident: string, { "tags": option_tags, "details": option_details, }?: { + tags?: Array; + details?: any; + }): void; + /** + * [convenience] + * + * @todo rename to "info" + */ + function info_(logger: type_logger_logic, incident: string, { "tags": option_tags, "details": option_details, }?: { + tags?: Array; + details?: any; + }): void; + /** + * [convenience] + * + * @todo rename to "notice" + */ + function notice_(logger: type_logger_logic, incident: string, { "tags": option_tags, "details": option_details, }?: { + tags?: Array; + details?: any; + }): void; + /** + * [convenience] + * + * @todo rename to "warning" + */ + function warning_(logger: type_logger_logic, incident: string, { "tags": option_tags, "details": option_details, }?: { + tags?: Array; + details?: any; + }): void; + /** + * [convenience] + * + * @todo rename to "error" + */ + function error_(logger: type_logger_logic, incident: string, { "tags": option_tags, "details": option_details, }?: { + tags?: Array; + details?: any; + }): void; + /** + * [convenience] + */ + function _send(entry: type_entry): void; + /** + * [convenience] + */ + function _debug(incident: string, { "tags": option_tags, "details": option_details, }?: { + tags?: Array; + details?: any; + }): void; + /** + * [convenience] + */ + function _info(incident: string, { "tags": option_tags, "details": option_details, }?: { + tags?: Array; + details?: any; + }): void; + /** + * [convenience] + */ + function _notice(incident: string, { "tags": option_tags, "details": option_details, }?: { + tags?: Array; + details?: any; + }): void; + /** + * [convenience] + */ + function _warning(incident: string, { "tags": option_tags, "details": option_details, }?: { + tags?: Array; + details?: any; + }): void; + /** + * [convenience] + */ + function _error(incident: string, { "tags": option_tags, "details": option_details, }?: { + tags?: Array; + details?: any; + }): void; + /** + * [convenience] + * + * @deprecated use ._debug instead! + */ + function debug(incident: string, details?: any, tags?: Array): void; + /** + * [convenience] + * + * @deprecated use ._info instead! + */ + function info(incident: string, details?: any, tags?: Array): void; + /** + * [convenience] + * + * @deprecated use ._notice instead! + */ + function notice(incident: string, details?: any, tags?: Array): void; + /** + * [convenience] + * + * @deprecated use ._warning instead! + */ + function warning(incident: string, details?: any, tags?: Array): void; + /** + * [convenience] + * + * @deprecated use ._error instead! + */ + function error(incident: string, details?: any, tags?: Array): 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; + /** + * @author fenris + */ + function join(parts: Array, glue?: 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 + * @deprecated use limit + */ + function cut(str: string, length: int, delimiter?: string): string; + /** + */ + function limit(str: string, options?: { + length?: int; + indicator?: string; + }): string; + /** + */ + function slice(str: string, size: int): Array; + /** + */ + function capitalize(str: 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.pit { + /** + */ + type type_date = { + year: int; + month: int; + day: int; + }; + /** + */ + type type_ywd = { + year: int; + week: int; + day: int; + }; + /** + */ + type type_time = { + hour: int; + minute: int; + second: int; + }; + /** + */ + type type_datetime = { + timezone_shift: int; + date: type_date; + time: (null | type_time); + }; + /** + */ + type type_pit = int; +} +declare namespace lib_plankton.pit { + /** + * @todo complete + */ + function timezone_name_to_timezone_shift(timezone_name: string): int; + /** + */ + function date_object_get_week_of_year(date: Date): int; + /** + */ + function to_unix_timestamp(pit: type_pit): int; + /** + */ + function from_unix_timestamp(unix_timestamp: int): type_pit; + /** + */ + function to_date_object(pit: type_pit): Date; + /** + * @todo test + */ + function to_datetime(pit: type_pit, { "timezone_shift": option_timezone_shift, }?: { + timezone_shift?: int; + }): type_datetime; + /** + */ + function from_datetime(datetime: type_datetime): type_pit; + /** + */ + function is_before(pit: type_pit, reference: type_pit): boolean; + /** + */ + function is_between(pit: type_pit, reference_left: type_pit, reference_right: type_pit): boolean; + /** + */ + function shift_hour(pit: type_pit, increment: int): type_pit; + /** + */ + function shift_day(pit: type_pit, increment: int): type_pit; + /** + */ + function shift_week(pit: type_pit, increment: int): type_pit; + /** + */ + function trunc_week(pit: type_pit): type_pit; + /** + */ + function now(): type_pit; + /** + * @param year year according to specified timezone shift + * @param week week according to specified timezone shift + * @return the begin of the week (monday, 00:00) + */ + function from_ywd(ywd: type_ywd, { "timezone_shift": option_timezone_shift, }?: { + timezone_shift?: int; + }): type_pit; + /** + * @todo timezone + */ + function to_ywd(pit: type_pit, { "timezone_shift": option_timezone_shift, }?: { + timezone_shift?: int; + }): type_ywd; + /** + * computes the point in time for switching to central european summer time + * + * @todo write tests + */ + function cest_switch_on(year: int): type_pit; + /** + * computes the point in time for switching away from central european summer time + * + * @todo write tests + */ + function cest_switch_off(year: int): type_pit; + /** + */ + function timezone_shift_ce(pit: type_pit): int; + /** + * [convenience] + */ + function to_datetime_ce(pit: type_pit): type_datetime; + /** + */ + function datetime_translate(datetime: type_datetime, timezone_shift: int): type_datetime; + /** + * [convenience] + */ + function datetime_translate_ce(datetime: type_datetime): type_datetime; + /** + */ + function timezone_shift_format(timezone_shift: int): string; + /** + */ + function date_format(date: type_date): string; + /** + */ + function time_format(time: type_time, { "show_seconds": option_show_seconds, }?: { + show_seconds?: boolean; + }): string; + /** + * @todo show timezone + */ + function datetime_format(datetime: (null | type_datetime), { "timezone_indicator": option_timezone_indicator, "show_timezone": option_show_timezone, "adjust_to_ce": option_adjust_to_ce, "omit_date": option_omit_date, }?: { + timezone_indicator?: string; + show_timezone?: boolean; + adjust_to_ce?: boolean; + omit_date?: boolean; + }): string; + /** + */ + function timespan_format(from: type_datetime, to: (null | type_datetime), { "timezone_indicator": option_timezone_indicator, "show_timezone": option_show_timezone, "adjust_to_ce": option_adjust_to_ce, "omit_date": option_omit_date, }?: { + timezone_indicator?: string; + show_timezone?: boolean; + adjust_to_ce?: boolean; + omit_date?: boolean; + }): string; +} +declare namespace lib_plankton.http_base { + /** + */ + type type_request = { + scheme: ("http" | "https"); + host: (null | string); + path: string; + version: string; + method: type_method; + query: (null | string); + headers: Record; + body: (null | Buffer); + }; + /** + */ + type type_response = { + version: (null | string); + status_code: type_status_code; + headers: Record; + body: (null | Buffer); + }; +} +declare namespace lib_plankton.http_base { + /** + */ + function encode_request(encode_method: ((method: type_method) => string), request: type_request): string; + /** + */ + function decode_request(decode_method: ((method_raw: string) => type_method), has_body: ((method: type_method) => boolean), request_raw: string): type_request; + /** + */ + function encode_response(encode_status_code: ((status_code: type_status_code) => string), get_status_text: ((status_code: type_status_code) => string), response: type_response): string; + /** + */ + function decode_response(decode_status_code: ((status_code_raw: string) => type_status_code), response_raw: string): type_response; + /** + * executes an HTTP request + * + * @todo define type_signal + */ + function call(has_body: ((method: type_method) => boolean), encode_method: ((method: type_method) => string), decode_status_code: ((status_code_raw: string) => type_status_code), request: type_request, { "timeout": option_timeout, "follow_redirects": option_follow_redirects, "implementation": option_implementation, }?: { + timeout?: (null | float); + follow_redirects?: boolean; + implementation?: ("fetch" | "http_module"); + }): Promise>; +} +declare namespace lib_plankton.http { + /** + * @author fenris + */ + enum enum_method { + options = "options", + head = "head", + get = "get", + delete = "delete", + post = "post", + put = "put", + patch = "patch" + } + /** + */ + enum enum_status_code { + continue_ = 100, + switching_protocols = 101, + early_hints = 103, + ok = 200, + created = 201, + accepted = 202, + non_authoritative_information = 203, + no_content = 204, + reset_content = 205, + partial_coentent = 206, + multiple_choices = 300, + moved_permanently = 301, + found = 302, + see_other = 303, + not_modified = 304, + temporary_redirect = 307, + permanent_redirect = 308, + bad_request = 400, + unauthorized = 401, + payment_required = 402, + forbidden = 403, + not_found = 404, + method_not_allowed = 405, + not_acceptable = 406, + proxy_authentication_required = 407, + request_timeout = 408, + conflict = 409, + gone = 410, + length_required = 411, + precondition_failed = 412, + payload_too_large = 413, + uri_too_long = 414, + unsupported_media_type = 415, + range_not_satisfiable = 416, + expectation_failed = 417, + i_m_a_teapot = 418, + unprocessable_entity = 422, + too_early = 425, + upgrade_required = 426, + precondition_required = 428, + too_many_requests = 429, + request_header_fields_too_large = 431, + unavailable_for_legal_reasons = 451, + internal_server_error = 500, + not_implemented = 501, + bad_gateway = 502, + service_unavailable = 503, + gateway_timeout = 504, + http_version_not_supported = 505, + variant_also_negotiates = 506, + insufficient_storage = 507, + loop_detected = 508, + not_extended = 510, + network_authentication = 511 + } + /** + * @author fenris + */ + type type_request = lib_plankton.http_base.type_request; + /** + * @author fenris + */ + type type_response = lib_plankton.http_base.type_response; +} +declare namespace lib_plankton.http { + /** + * @author fenris + */ + function encode_method(method: enum_method): string; + /** + * @author fenris + */ + function decode_method(method_raw: string): enum_method; + /** + * @author fenris + */ + function has_body(method: enum_method): boolean; + /** + * @author fenris + */ + function encode_request(request: type_request): string; + /** + * @author fenris + */ + function decode_request(request_raw: string): type_request; + /** + * @author fenris + */ + function encode_response(response: type_response): string; + /** + * @author fenris + */ + function decode_response(response_raw: string): type_response; + /** + * executes an HTTP request + * + * @todo define type_signal + */ + function call(request: type_request, { "timeout": option_timeout, "follow_redirects": option_follow_redirects, "implementation": option_implementation, }?: { + timeout?: (null | float); + follow_redirects?: boolean; + implementation?: ("fetch" | "http_module"); + }): Promise; +} +declare namespace lib_plankton.ical { + /** + */ + type type_rrule = { + freq?: string; + byday?: string; + bymonth?: string; + }; + /** + */ + type type_offset = string; + /** + */ + /** + */ + export enum enum_class { + public = "public", + private = "private", + confidential = "confidential" + } + /** + */ + export enum enum_event_status { + tentative = "tentative", + confirmed = "confirmed", + cancelled = "cancelled" + } + /** + */ + export enum enum_transp { + opaque = "opaque", + transparent = "transparent" + } + /** + */ + type type_tzid = string; + /** + */ + export type type_date = { + year: int; + month: int; + day: int; + }; + /** + */ + export type type_time = { + hour: int; + minute: int; + second: int; + utc: boolean; + }; + /** + */ + export type type_datetime = { + date: type_date; + time: (null | type_time); + }; + /** + */ + export type type_dt = { + tzid: type_tzid; + value: type_datetime; + }; + /** + */ + type type_duration = { + negative: boolean; + weeks?: int; + days?: int; + hours?: int; + minutes?: int; + seconds?: int; + }; + /** + */ + type type_vtimezone = { + tzid?: type_tzid; + standard?: { + dtstart: type_datetime; + rrule: type_rrule; + tzoffsetfrom?: type_offset; + tzoffsetto?: type_offset; + }; + daylight?: { + dtstart: type_datetime; + rrule: type_rrule; + tzoffsetfrom?: type_offset; + tzoffsetto?: type_offset; + }; + }; + /** + * @see https://www.rfc-editor.org/rfc/rfc5545#section-3.6.1 + */ + export type type_vevent = { + uid: string; + dtstamp: type_datetime; + dtstart?: type_dt; + class?: enum_class; + created?: type_datetime; + description?: string; + geo?: { + latitude: float; + longitude: float; + }; + last_modified?: type_datetime; + location?: string; + /** + * @see https://www.rfc-editor.org/rfc/rfc5545#section-3.8.4.3 + */ + organizer?: { + value?: string; + cn?: string; + dir?: string; + sent_by?: string; + }; + priority?: int; + sequence?: int; + status?: enum_event_status; + summary?: string; + transp?: enum_transp; + url?: string; + recurid?: any; + rrule?: type_rrule; + dtend?: type_dt; + duration?: type_duration; + attach?: any; + attendee?: string; + categories?: Array; + comment?: any; + contact?: any; + exdate?: any; + rstatus?: any; + related?: any; + resources?: any; + rdate?: any; + x_props?: Record; + iana_props?: Record; + }; + /** + * @see https://www.rfc-editor.org/rfc/rfc5545#section-3.4 + */ + export type type_vcalendar = { + version: string; + prodid: string; + vevents: Array; + calscale?: string; + method?: string; + vtimezone?: type_vtimezone; + x_props?: Record; + iana_props?: Record; + }; + export {}; +} +declare namespace lib_plankton.ical { + /** + */ + function datetime_to_unixtimestamp(datetime: type_datetime): int; + /** + * @see https://www.rfc-editor.org/rfc/rfc5545 + * @see https://icalendar.org/iCalendar-RFC-5545/ + * @todo implement edge cases + */ + function ics_decode_multi(ics_raw: string, { ignore_unhandled_instruction_keys, from_fucked_up_wordpress, }?: { + ignore_unhandled_instruction_keys?: boolean; + from_fucked_up_wordpress?: boolean; + }): Array; + /** + * @see https://www.rfc-editor.org/rfc/rfc5545 + * @see https://icalendar.org/iCalendar-RFC-5545/ + * @todo implement edge cases + */ + function ics_decode(ics: string, { ignore_unhandled_instruction_keys, from_fucked_up_wordpress, }?: { + ignore_unhandled_instruction_keys?: boolean; + from_fucked_up_wordpress?: boolean; + }): type_vcalendar; + /** + * @todo method + * @todo add missing fields + */ + function ics_encode(vcalendar: type_vcalendar): string; +} +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 { + /** + */ + type type_source = any; + /** + */ + type type_target = string; + /** + * @author fenris + */ + export function encode(source: type_source, options?: { + formatted?: boolean; + }): type_target; + /** + * @author fenris + */ + export function decode(target: type_target): type_source; + /** + * @author fenris + */ + export function implementation_code(): lib_plankton.code.type_code; + export {}; +} +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.telegram { + /** + */ + type type_chat_id = int; + /** + * @see https://core.telegram.org/bots/api#user + */ + type type_user = { + id: int; + is_bot?: boolean; + first_name: string; + last_name?: string; + username?: string; + language_code?: string; + is_premium?: boolean; + added_to_attachment_menu?: boolean; + can_join_groups?: boolean; + can_read_all_group_messages?: boolean; + supports_inline_queries?: boolean; + can_connect_to_business?: boolean; + has_main_web_app?: boolean; + }; + /** + * @see https://core.telegram.org/bots/api#chat + */ + type type_chat = { + id: int; + type: string; + title?: string; + username?: string; + first_name?: string; + last_name?: string; + is_forum?: boolean; + }; + /** + * @see https://core.telegram.org/bots/api#chatfullinfo + * @todo complete + */ + type type_chat_full_info = { + id: int; + type: string; + accent_color_id: int; + max_reaction_count: int; + }; + /** + * @see https://core.telegram.org/bots/api#message + * @todo complete + */ + type type_message = { + message_id: int; + message_thread_id?: int; + from?: type_user; + sender_chat?: type_chat; + sender_boost_count?: int; + sender_business_bot?: type_user; + date: int; + business_connection_id?: string; + chat: type_chat; + forward_origin?: type_message_origin; + is_topic_message?: boolean; + is_automatic_forward?: boolean; + reply_to_message?: type_message; + external_reply?: type_external_reply_info; + quote?: type_text_quote; + reply_to_story?: type_story; + via_bot?: type_user; + edit_date?: int; + has_protected_content?: boolean; + is_from_offline?: boolean; + media_group_id?: string; + author_signature?: string; + paid_star_count?: int; + text?: string; + entities?: Array; + link_preview_options?: type_link_preview_options; + effect_id?: string; + animation?: type_animation; + audio?: type_audio; + document?: type_document; + paid_media?: type_paid_media_info; + photo?: Array; + sticker?: type_sticker; + story?: type_story; + video?: type_video; + video_note?: type_video_note; + voice?: type_voice; + caption?: string; + caption_entities?: Array; + show_caption_above_media?: boolean; + has_media_spoiler?: boolean; + contact?: type_contact; + dice?: type_dice; + game?: type_game; + }; + /** + * @see https://core.telegram.org/bots/api#messageid + */ + type type_message_id = { + message_id: int; + }; + /** + * @see https://core.telegram.org/bots/api#inaccessiblemessage + */ + type type_inaccessible_message = { + chat: type_chat; + message_id: int; + date: int; + }; + /** + * @see https://core.telegram.org/bots/api#maybeinaccessiblemessage + */ + type type_maybe_inaccessible_message = (type_message | type_inaccessible_message); + /** + * @see https://core.telegram.org/bots/api#messageentity + */ + type type_message_entity = { + type: string; + offset: int; + length: int; + url?: string; + user?: type_user; + language?: string; + custom_emoji_id?: string; + }; + /** + * @see https://core.telegram.org/bots/api#textquote + */ + type type_text_quote = { + text: string; + entities?: Array; + position: int; + is_manual?: boolean; + }; + /** + * @see https://core.telegram.org/bots/api#externalreplyinfo + * @todo complete + */ + type type_external_reply_info = { + origin: type_message_origin; + chat?: type_chat; + }; + /** + * @see https://core.telegram.org/bots/api#replyparameters + * @todo complete + */ + type type_reply_parameters = { + message_id: int; + chat_id?: (int | string); + }; + /** + * @see https://core.telegram.org/bots/api#messageorigin + */ + type type_message_origin = (type_message_origin_user | type_message_origin_hidden_user | type_message_origin_chat | type_message_origin_channel); + /** + * @see https://core.telegram.org/bots/api#messageoriginuser + */ + type type_message_origin_user = { + type: string; + date: int; + sender_user: type_user; + }; + /** + * @see https://core.telegram.org/bots/api#messageoriginhiddenuser + */ + type type_message_origin_hidden_user = { + type: string; + date: int; + sender_user_name: string; + }; + /** + * @see https://core.telegram.org/bots/api#messageoriginchat + */ + type type_message_origin_chat = { + type: string; + date: int; + sender_chat: type_chat; + author_signature?: string; + }; + /** + * @see https://core.telegram.org/bots/api#messageoriginchannel + */ + type type_message_origin_channel = { + type: string; + date: int; + chat: type_chat; + message_id: int; + author_signature?: string; + }; + /** + * @see https://core.telegram.org/bots/api#photosize + */ + type type_photo_size = { + file_id: string; + file_unique_id: string; + width: int; + height: int; + file_size?: int; + }; + /** + * @see https://core.telegram.org/bots/api#animation + */ + type type_animation = { + file_id: string; + file_unique_id: string; + width: int; + height: int; + duration: int; + thumbnail?: type_photo_size; + file_name?: string; + mime_type?: string; + file_size?: int; + }; + /** + * @see https://core.telegram.org/bots/api#audio + * @todo complete + */ + type type_audio = { + file_id: string; + file_unique_id: string; + duration: int; + }; + /** + * @see https://core.telegram.org/bots/api#document + * @todo complete + */ + type type_document = { + file_id: string; + file_unique_id: string; + thumbnait?: type_photo_size; + }; + /** + * @see https://core.telegram.org/bots/api#story + */ + type type_story = { + chat: type_chat; + id: int; + }; + /** + * @see https://core.telegram.org/bots/api#video + * @todo complete + */ + type type_video = { + file_id: string; + file_unique_id: string; + width: int; + height: int; + duration: int; + }; + /** + * @see https://core.telegram.org/bots/api#videonote + */ + type type_video_note = { + file_id: string; + file_unique_id: string; + length: int; + duration: int; + thumbnail?: type_photo_size; + file_size?: int; + }; + /** + * @see https://core.telegram.org/bots/api#videonote + */ + type type_voice = { + file_id: string; + file_unique_id: string; + length: int; + duration: int; + mime_type?: string; + file_size?: int; + }; + /** + * @see https://core.telegram.org/bots/api#paidmediainfo + */ + type type_paid_media_info = { + star_count: int; + paid_media: Array; + }; + /** + * @see https://core.telegram.org/bots/api#paidmedia + */ + type type_paid_media = (type_paid_media_preview | type_paid_media_photo | type_paid_media_video); + /** + * @see https://core.telegram.org/bots/api#paidmediapreview + */ + type type_paid_media_preview = { + type: string; + width?: int; + height?: int; + duration?: int; + }; + /** + * @see https://core.telegram.org/bots/api#paidmediaphoto + */ + type type_paid_media_photo = { + type: string; + photo: Array; + }; + /** + * @see https://core.telegram.org/bots/api#paidmediavideo + */ + type type_paid_media_video = { + type: string; + video: type_video; + }; + /** + * @see https://core.telegram.org/bots/api#contact + */ + type type_contact = { + phone_number: string; + first_name: string; + last_name?: string; + user_id?: int; + vcard: string; + }; + /** + * @see https://core.telegram.org/bots/api#dice + */ + type type_dice = { + emoji: string; + value: int; + }; + /** + * @see https://core.telegram.org/bots/api#linkpreviewoptions + */ + type type_link_preview_options = { + is_disabled?: boolean; + url?: string; + prefer_small_media?: boolean; + prefer_large_media?: boolean; + show_above_text?: boolean; + }; + /** + * @see https://core.telegram.org/bots/api#sticker + * @todo complete + */ + type type_sticker = { + file_id: string; + file_unique_id: string; + type: string; + width: int; + height: int; + is_animated: boolean; + is_video: boolean; + }; + /** + * @see https://core.telegram.org/bots/api#game + */ + type type_game = { + title: string; + description: string; + photo: Array; + text?: string; + text_entities?: Array; + animation?: type_animation; + }; + /** + * @see https://core.telegram.org/bots/api#update + * @todo complete + */ + type type_update = { + update_id: int; + }; +} +declare namespace lib_plankton.telegram { + /** + * @see https://core.telegram.org/bots/api#getupdates + */ + function bot_call_get_updates(token: string): Promise>; + /** + * @see https://core.telegram.org/bots/api#sendmessage + */ + function bot_call_send_message(token: string, chat_id: (int | string), text: string): Promise; +} +declare namespace lib_plankton.file { + /** + * @author fenris + */ + function exists(path: string): Promise; + /** + * @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; + /** + */ + function delete_(path: string): Promise; +} +declare namespace lib_plankton.object { + /** + * @author fenris + * @deprecated use the "??" operator instead + */ + function fetch(object: Object, fieldname: string, options?: { + fallback?: type_value; + escalate?: boolean; + }): type_value; + /** + */ + function map(object_from: Record, transformator: ((value_from: type_from, key?: string) => type_to)): Record; + /** + * gibt ein Objekt mit bestimmten Einträgen des Eingabe-Objekts zurück + */ + function filter(object_from: Record, predicate: ((value_from: type_value, key?: string) => boolean)): Record; + /** + * wandelt ein Array mit Einträgen der Form {key,value} in ein entsprechendes Objekt um + * + * @deprecated use Object.fromEntries instead! + */ + function from_array(array: Array<{ + key: string; + value: type_value; + }>): Record; + /** + * wandelt ein Objekt in ein entsprechendes Array mit Einträgen der Form {key,value} um + * + * @deprecated use Object.entries insetad! + */ + function to_array(object: Record): Array<{ + key: string; + value: type_value; + }>; + /** + * gibt eine Liste von Schlüsseln eines Objekts zurück + * + * @deprecated use Object.keys instead! + */ + function keys(object: Record): Array; + /** + * gibt eine Liste von Werten eines Objekts zurück + * + * @deprecated use Object.values instead! + */ + function values(object: Record): Array; + /** + * liest ein Baum-artiges Objekt an einer bestimmten Stelle aus + */ + function path_read(object: Object, path: string, options?: { + fallback?: type_value; + escalate?: boolean; + }): type_value; + /** + * schreibt einen Wert an eine bestimmte Stelle in einem Baum-artigen Objekt + */ + function path_write(object: Object, path: string, value: type_value, construct?: boolean): void; + /** + * prüft ob ein Objekt einem bestimmten Muster entspricht + * + * @deprecated not very useful + */ + function matches(object: Record, pattern: Record, options?: { + collate?: ((value_pattern: type_value_pattern, value_object: type_value_object) => boolean); + }): boolean; + /** + * erzeugt eine Projektion eines Baum-artigen Objekts in ein Listen-artiges Objekt + */ + function flatten(value: any, options?: { + separator?: string; + key_for_array_element?: ((index: int) => string); + }): Record; + /** + * @deprecated use Object.assign instead! + */ + function clash(x: Record, y: Record, options?: { + overwrite?: boolean; + hooks?: { + existing?: ((key?: string, value_old?: any, value_new?: any) => void); + }; + }): Record; + /** + * @deprecated use Object.assign instead! + */ + function patch(core: (null | Record), mantle: (null | Record), options?: { + deep?: boolean; + path?: (null | string); + }): void; + /** + * @deprecated use Object.assign instead! + */ + function patched(core: Record, mantle: Record, options?: { + deep?: boolean; + }): Record; + /** + * @deprecated use Object.assign instead! + */ + function attached(object: Record, key: string, value: any): Record; + /** + * @author fenris + */ + function copy(object: Record): Record; +} +declare namespace lib_plankton.pair { + /** + */ + type type_pair = { + first: type_first; + second: type_second; + }; +} +declare namespace lib_plankton.pair { + /** + */ + function swap(pair: type_pair): type_pair; + /** + */ + function show(pair: type_pair, options?: { + show_first?: ((first: type_first) => string); + show_second?: ((second: type_second) => string); + }): string; +} +declare namespace lib_plankton.list { + /** + */ + type type_separation = { + yes: Array; + no: Array; + }; + /** + */ + type type_result_max = (null | { + index: int; + element: type_element; + value: type_value; + }); +} +declare namespace lib_plankton.list { + /** + * returns a certain list of integer numbers + */ + function range(from: int, to: int, options?: { + step?: int; + }): Array; + /** + * returns a certain list of consecutiv integer numbers, beginning with 0 + */ + function sequence(length: int): Array; + /** + */ + function from_iterator(iterator: Iterator): Array; + /** + */ + function is_empty(list: Array): boolean; + /** + * combines two lists into one + * + * @param {boolean} [options.cut] whether the result list will be as long as the shortest input list or an exception is thrown if they have different lengths; default: true + */ + function zip(list_first: Array, list_second: Array, options?: { + cut?: boolean; + }): Array>; + /** + * checks whether two lists are equal + * + * @todo define common function "equals" and default predicate to + */ + function equals(list1: Array, list2: Array, options?: { + collate_element?: ((element1: type_element, element2: type_element) => boolean); + }): boolean; + /** + * creates a list with the elements from the input list, which fulfil a certain predicate (~ filter) + */ + function keep(list: Array, predicate: ((element: type_element) => boolean)): Array; + /** + * creates a list with the elements from the input list, which do not fulfil a certain predicate (~ dual filter) + */ + function drop(list: Array, predicate: ((element: type_element) => boolean)): Array; + /** + */ + function filter_inplace(list: Array, predicate: ((element: type_element) => boolean)): void; + /** + * returns a list with no duplicates (like unix' "unique") + */ + function cleaned(list: Array, options?: { + collate_element?: ((x: type_element, y: type_element) => boolean); + }): Array; + /** + * creates a binary partition of the list according to a given predicate + */ + function separate(list: Array, predicate: ((element: type_element) => boolean)): type_separation; + /** + */ + function clone(list: Array): Array; + /** + */ + function reversed(list: Array): Array; + /** + * @todo use Array.toSorted? + */ + function sorted(list: Array, options: { + compare_element?: ((element1: type_element, element2: type_element) => boolean); + }): Array; + /** + * die Liste in gleich große Blöcke zerlegen + */ + function chop(list: Array, chunk_size: int): Array>; + /** + */ + function group(list: Array, collate_element: ((x: type_element, y: type_element) => boolean)): Array>; + /** + */ + function has(list: Array, predicate: ((element: type_element) => boolean)): boolean; + /** + * @deprecate use Array.includes or Array.some + */ + function contains(list: Array, element: type_element, options: { + collate_element?: ((element1: type_element, element2: type_element) => boolean); + }): boolean; + /** + * retrieves the element and its index of the list, which has the maximum value + */ + function max(list: Array, target_function: ((element: type_element) => type_value), options: { + compare_value: ((value1: type_value, value2: type_value) => boolean); + }): type_result_max; + /** + * retrieves the element and its index of the list, which has the mininum value + */ + function min(list: Array, target_function: (element: type_element) => type_value, options: { + compare_value: ((value1: type_value, value2: type_value) => boolean); + }): type_result_max; + /** + * implements the idea of arithmetic distribution like in "(a+b)·(c+d) = (a·c)+(a·d)+(b·c)+(b·d)" + * example: distribute([[1,2],[3],[4,5,6]]) = [[1,3,4],[1,3,5],[1,3,6],[2,3,4],[2,3,5],[2,3,6]] + */ + function distribute(lists: Array>): Array>; + /** + */ + function contrast(list_left: Array, extract_key_left: ((left: type_left) => string), list_right: Array, extract_key_right: ((right: type_right) => string)): { + both: Array<{ + key: string; + left: type_left; + right: type_right; + }>; + only_left: Array<{ + key: string; + left: type_left; + }>; + only_right: Array<{ + key: string; + right: type_right; + }>; + }; +} +declare namespace lib_plankton.conf { + /** + */ + type type_schema = ({ + enum?: Array; + default?: any; + description?: string; + } | { + type: "null"; + description?: string; + } | { + type: "boolean"; + nullable?: boolean; + enum?: Array; + default?: boolean; + description?: string; + } | { + type: "integer"; + nullable?: boolean; + enum?: Array; + default?: int; + description?: string; + } | { + type: "number"; + nullable?: boolean; + enum?: Array; + default?: number; + description?: string; + } | { + type: "string"; + nullable?: boolean; + enum?: Array; + default?: string; + description?: string; + } | { + type: "array"; + nullable?: boolean; + items: type_schema; + enum?: Array>; + default?: Array; + description?: string; + } | { + type: "object"; + nullable?: boolean; + properties?: Record; + required?: Array; + additionalProperties?: (false | type_schema); + enum?: Array>; + default?: Record; + description?: string; + } | { + anyOf: Array; + default?: any; + } | { + allOf: Array; + } | { + oneOf: Array; + } | { + not: type_schema; + }); + /** + */ + type type_report = { + incident: string; + details: Record; + }; + /** + */ + type type_adaption = { + reports: Array; + result: lib_plankton.pod.type_pod; + }; +} +declare namespace lib_plankton.conf { + /** + * @todo versioning + */ + function refine(schema: type_schema, value_raw: any): type_result; + /** + */ + function load(schema: type_schema, path: (null | string)): Promise; +} +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/libs/plankton/plankton.js b/libs/plankton/plankton.js new file mode 100644 index 0000000..f28ce3c --- /dev/null +++ b/libs/plankton/plankton.js @@ -0,0 +1,8590 @@ +/* +This file is part of »bacterio-plankton:base«. + +Copyright 2016-2024 '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-2024 '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-2024 '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 { + let 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-2024 '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-2024 '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 + */ +class class_observer { + /** + * @author frac + */ + constructor() { + this.counter = 0; + this.actions = {}; + this.buffer = []; + } + /** + * @author frac + */ + empty() { + return (Object.keys(this.actions).length == 0); + } + /** + * @author frac + */ + flush() { + this.actions = {}; + } + /** + * @author frac + */ + set(id, action) { + this.actions[id] = action; + } + /** + * @author frac + */ + del(id) { + delete this.actions[id]; + } + /** + * @author frac + */ + add(action) { + this.set((this.counter++).toString(), action); + } + /** + * @author frac + */ + notify(information = {}, delayed = false) { + if (delayed) { + this.buffer.push(information); + } + else { + Object.keys(this.actions).forEach(id => this.actions[id](information)); + } + } + /** + * @author frac + */ + rollout() { + this.buffer.forEach(information => this.notify(information, false)); + this.buffer = []; + } +} +/** + * @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-2024 '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 + */ +class class_error extends Error { + /** + * @author frac + */ + constructor(message, suberrors = []) { + super(message); + this.suberrors = suberrors; + this.mess = message; + } + /** + * @override + * @author frac + */ + toString() { + return ( /*super.toString()*/this.mess + " " + ("[" + this.suberrors.map(x => x.toString()).join(",") + "]")); + } +} +/* +This file is part of »bacterio-plankton:base«. + +Copyright 2016-2024 '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) { + /** + * returns the current UNIX timestamp + * + * @author fenris + */ + function get_current_timestamp(rounded = false) { + const 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; + /** + */ + function buffer_show(buffer, { "block_size": option_block_size = 20, "break_char": option_break_char = "\n", } = {}) { + let output = ""; + let count = 0; + // @ts-ignore + for (const entry of buffer) { + count = ((count + 1) % option_block_size); + output += ((typeof (entry) === "string") + ? + entry.charCodeAt(0) + : + entry).toString(16).toUpperCase().padStart(2, "0"); + output += ((count === 0) ? option_break_char : " "); + } + return output; + } + base.buffer_show = buffer_show; + })(base = lib_plankton.base || (lib_plankton.base = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:pod«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:pod« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:pod« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:pod«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var pod; + (function (pod_1) { + /** + * @author fenris + */ + function make_empty() { + return { + "kind": "empty" + }; + } + pod_1.make_empty = make_empty; + /** + * @author fenris + */ + function make_filled(value) { + return { + "kind": "filled", + "value": value + }; + } + pod_1.make_filled = make_filled; + /** + * whether the pod is filled + * + * @author fenris + */ + function is_filled(pod) { + return (pod.kind === "filled"); + } + pod_1.is_filled = is_filled; + /** + * return the value, stored in the pod-wrapper + * + * @author fenris + */ + function cull(pod) { + if (!is_filled(pod)) { + throw (new Error("cull from empty")); + } + else { + return pod.value; + } + } + pod_1.cull = cull; + /** + * to pass on a empty-pod or to use a filled-pod + * + * @author fenris + */ + function propagate(pod, function_) { + if (!is_filled(pod)) { + return make_empty(); + } + else { + return make_filled(function_(pod.value)); + } + } + pod_1.propagate = propagate; + /** + * @author fenris + */ + function distinguish(pod, function_empty, function_filled) { + return ((!is_filled(pod)) + ? function_empty() + : function_filled(pod.value)); + } + pod_1.distinguish = distinguish; + /** + */ + function show(pod, options = {}) { + options = Object.assign({ + "show_value": value => String(value), + }, options); + if (!is_filled(pod)) { + return "<·>"; + } + else { + return ("<- " + options.show_value(pod.value) + " ->"); + } + } + pod_1.show = show; + })(pod = lib_plankton.pod || (lib_plankton.pod = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:pod«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:pod« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:pod« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:pod«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var pod; + (function (pod) { + /** + */ + class class_pod { + constructor(subject) { this.subject = subject; } + tear() { return this.subject; } + static empty() { return (new class_pod(pod.make_empty())); } + static filled(value) { return (new class_pod(pod.make_filled(value))); } + is_empty() { return (!pod.is_filled(this.subject)); } + is_filled() { return pod.is_filled(this.subject); } + cull() { return pod.cull(this.subject); } + show(show_value = undefined) { return pod.show(this.subject, show_value); } + toString() { return this.show(); } + propagate(function_) { return new class_pod(pod.propagate(this.subject, function_)); } + distinguish(function_empty, function_filled) { return pod.distinguish(this.subject, function_empty, function_filled); } + } + pod.class_pod = class_pod; + })(pod = lib_plankton.pod || (lib_plankton.pod = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:call«. + +Copyright 2016-2024 '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 . + */ +/** + * might be completely obsolete + */ +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, options = { + "serial": false, + }) { + const decorate = function (promise, name) { + return (() => promise_then_append(promise(), value => promise_resolve({ "key": name, "value": value }))); + }; + if (options.serial) { + return (promise_then_append(promise_condense(Object.keys(promises) + .map(name => decorate(promises[name], name))), list => promise_resolve(Object.fromEntries(list.map(({ "key": key, "value": value }) => ([key, value])))))); + } + else { + return (promise_then_append(promise_all(Object.keys(promises) + .map(name => decorate(promises[name], name)) + .map(promise => promise())), list => promise_resolve(Object.fromEntries(list.map(({ "key": key, "value": value }) => ([key, value])))))); + } + } + call.promise_group = promise_group; + /** + * @author fenris + */ + function promise_wrap(promise, transformator_result, transformator_reason = lib_plankton.call.id) { + return (promise_make((resolve, reject) => { + promise_then_close(promise, result => resolve(transformator_result(result)), reason => reject(transformator_reason(reason))); + })); + } + call.promise_wrap = promise_wrap; + /** + * @author fenris + */ + /* + export function promise_show(label : string) : (result : type_result)=>type_promise { + return ( + result => promise_make( + (resolve, reject) => { + // lib_plankton.log.info(label + ": " + instance_show(result)); + process.stdout.write(label + ": " + instance_show(result)); + resolve(result); + } + ) + ); + } + */ + /** + * @author fenris + */ + /* + export function promise_log(result : type_result) : (result : type_result)=>type_promise { + return promise_show("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; + })(call = lib_plankton.call || (lib_plankton.call = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:call«. + +Copyright 2016-2024 '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 . + */ +/** + * initializer might be obsolete, since promises are reusable after having been resolved or rejected + */ +var lib_plankton; +(function (lib_plankton) { + var call; + (function (call) { + /** + * @author fenris + */ + let enum_initializer_state; + (function (enum_initializer_state) { + enum_initializer_state[enum_initializer_state["initial"] = 0] = "initial"; + enum_initializer_state[enum_initializer_state["waiting"] = 1] = "waiting"; + enum_initializer_state[enum_initializer_state["successful"] = 2] = "successful"; + enum_initializer_state[enum_initializer_state["failed"] = 3] = "failed"; + })(enum_initializer_state = call.enum_initializer_state || (call.enum_initializer_state = {})); + /** + * @author fenris + */ + function initializer_make(fetcher) { + let subject = { + "fetcher": fetcher, + "state": enum_initializer_state.initial, + "queue": [], + "result": undefined, + "reason": undefined, + }; + return subject; + } + call.initializer_make = initializer_make; + /** + * @author fenris + */ + function initializer_actuate(subject) { + switch (subject.state) { + case enum_initializer_state.successful: { + subject.queue.forEach(entry => entry.resolve(subject.result)); + break; + } + case enum_initializer_state.failed: { + subject.queue.forEach(entry => entry.reject(subject.reason)); + break; + } + default: { + throw (new Error(`unhandled state ${subject.state}`)); + break; + } + } + } + /** + * @author fenris + */ + function initializer_reset(subject) { + subject.state = enum_initializer_state.initial; + subject.queue = []; + } + call.initializer_reset = initializer_reset; + /** + * @author fenris + */ + function initializer_state(subject) { + return subject.state; + } + call.initializer_state = initializer_state; + /** + * @author fenris + */ + function initializer_get(subject) { + switch (subject.state) { + case enum_initializer_state.initial: { + subject.state = enum_initializer_state.waiting; + return (call.promise_make((resolve, reject) => { + subject.queue.push({ "resolve": resolve, "reject": reject }); + subject.fetcher().then(result => { + subject.state = enum_initializer_state.successful; + subject.result = result; + initializer_actuate(subject); + }, reason => { + subject.state = enum_initializer_state.failed; + subject.reason = reason; + initializer_actuate(subject); + }); + })); + break; + } + case enum_initializer_state.waiting: { + return (call.promise_make((resolve, reject) => { + subject.queue.push({ "resolve": resolve, "reject": reject }); + })); + break; + } + case enum_initializer_state.successful: { + return (call.promise_resolve(subject.result)); + break; + } + case enum_initializer_state.failed: { + return (call.promise_reject(subject.reason)); + break; + } + default: { + throw (new Error(`unhandled state ${subject.state}`)); + break; + } + } + } + call.initializer_get = initializer_get; + /** + * @author fenris + */ + function initializer_get_sync(subject) { + switch (subject.state) { + case enum_initializer_state.successful: { + return subject.result; + break; + } + case enum_initializer_state.failed: { + throw subject.reason; + break; + } + default: { + throw (new Error(`unhandled state ${subject.state}`)); + break; + } + } + } + /** + * @author fenris + */ + function initializer_set_sync(subject, result) { + switch (subject.state) { + case enum_initializer_state.successful: { + subject.result = result; + break; + } + case enum_initializer_state.failed: { + subject.state = enum_initializer_state.successful; + subject.result = result; + break; + } + default: { + throw (new Error(`unhandled state ${subject.state}`)); + break; + } + } + } + })(call = lib_plankton.call || (lib_plankton.call = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:call«. + +Copyright 2016-2024 '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_plankton.pod.make_empty(), + "right": lib_plankton.pod.make_empty(), + }; + let finish = function () { + if (lib_plankton.pod.is_filled(object.left) + && + lib_plankton.pod.is_filled(object.right)) { + let result = { + "left": lib_plankton.pod.cull(object.left), + "right": lib_plankton.pod.cull(object.right), + }; + convey(result); + } + else { + // do nothing + } + }; + deferral_use(deferral_left, input, output_left => { + object.left = lib_plankton.pod.make_filled(output_left); + finish(); + }); + deferral_use(deferral_right, input, output_right => { + object.right = lib_plankton.pod.make_filled(output_right); + finish(); + }); + })); + } + call.deferral_compose_parallel = deferral_compose_parallel; + /** + * @author fenris + * @desc repeatedly applied serial composition + */ + function deferral_chain(members) { + return (members.reduce( + // (result, current) => deferral_compose_serial(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-2024 '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-2024 '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) { + /** + * converts the "arguments"-map into an array + * + * @param {Object} args + * @author fenris + */ + function args2list(args) { + return Object.keys(args).map(key => args[key]); + } + call.args2list = args2list; + /** + * just the empty function; useful for some callbacks etc. + * + * @author fenris + */ + function nothing() { + } + call.nothing = nothing; + /** + * just the identity; useful for some callbacks etc.; defined as function instead of const for using type parameters + * + * @author fenris + */ + function id(x) { + return x; + } + call.id = id; + /** + * just the identity; useful for some callbacks etc. + * + * @author fenris + */ + function const_(x) { + return (y => x); + } + call.const_ = const_; + /** + * composes two functions (i.e. returns a function that return the result of the successive execution of both input-functions) + * + * @param {function} function_f + * @param {function} function_g + * @author fenris + */ + function compose(function_f, function_g) { + return (function (x) { + // return function_g(function_f(x)); + return function_g(function_f.apply(function_f, args2list(arguments))); + }); + } + call.compose = compose; + /** + * @author fenris + */ + function curryfy_real(f, n) { + switch (n) { + case 0: { + throw (new Error("[curryfy] impossible")); + // break; + } + case 1: { + return f; + // break; + } + default: { + return (function (x) { + return (curryfy_real(function () { return f.apply(f, [x].concat(args2list(arguments))); }, n - 1)); + }); + // break; + } + } + } + /** + * transforms a function with sequential input to a function with leveled input; example: add(2,3) = curryfy(add)(2)(3) + * + * @param {function} f + * @return {function} the currified version of the in put function + * @author fenris + */ + function curryfy(f) { + return curryfy_real(f, f.length); + } + call.curryfy = curryfy; + /** + * @author fenris + */ + function convey(value, functions) { + let result = value; + functions.forEach(function_ => { + result = function_(result); + }); + return result; + } + call.convey = convey; + /** + */ + class class_value_wrapper { + /** + */ + constructor(value) { + this.value = value; + } + /** + */ + convey(function_) { + return (new class_value_wrapper(function_(this.value))); + } + /** + */ + cull() { + return this.value; + } + } + /** + */ + function wrap(value) { + return (new class_value_wrapper(value)); + } + call.wrap = wrap; + /** + * @author fenris + */ + function timeout(procedure, delay_in_seconds) { + return ( + /*window.*/ setTimeout(procedure, Math.floor(delay_in_seconds * 1000))); + } + call.timeout = timeout; + /** + * Promise version of "setTimeout" + * + * @author fenris + */ + function defer(seconds, action) { + return (new Promise((resolve, reject) => { + setTimeout(() => resolve(action()), Math.floor(seconds * 1000)); + })); + } + call.defer = defer; + /** + * a definition for a value being "defined" + * + * @author neuc + */ + function is_def(obj, options = {}) { + options = Object.assign({ + "null_is_valid": false, + }, options); + return (!((typeof (obj) === "undefined") + || + (!options.null_is_valid && (obj === null)))); + } + call.is_def = is_def; + /** + * returns the value if set and, when a type is specified, if the type is correct, if not return default_value + * + * @author neuc + */ + function def_val(value, default_value, options = {}) { + options = Object.assign({ + "type": null, + "null_is_valid": false, + }, options); + if (is_def(value, { "null_is_valid": options.null_is_valid }) + && + (is_def(options.type) + ? ((typeof (value) === options.type) + || + ((value === null) + && + options.null_is_valid)) + : true)) { + return value; + } + else { + return default_value; + } + } + call.def_val = def_val; + ; + /** + * provides the call for an attribute of a class as a regular function; useful for processing lists of objects + * + * @param {string} name the name of the attribute + * @return {function} + * @author fenris + */ + function attribute(name) { + return (object => object[name]); + } + call.attribute = attribute; + /** + * provides a method of a class as a regular function; useful for processing lists of objects + * + * @param {string} name the name of the method + * @return {function} + * @author fenris + */ + function method(name) { + return (function (object) { return object[name].apply(object, args2list(arguments).slice(1)); }); + } + call.method = method; + /** + * @author fenris + */ + function distinguish(coproduct, handlers, options = {}) { + options = Object.assign({ + "fallback": null, + }, options); + if (coproduct.kind in handlers) { + const handler = handlers[coproduct.kind]; + return handler(coproduct.data); + } + else { + const message = ("unhandled kind '" + coproduct.kind + "'"); + if (options.fallback !== null) { + console.warn(message); + return options.fallback(coproduct); + } + else { + throw (new Error(message)); + } + } + } + call.distinguish = distinguish; + /** + */ + function try_catch_wrap(get_value) { + try { + return { + "value": get_value(), + "error": null, + }; + } + catch (error) { + return { + "value": null, + "error": error, + }; + } + } + call.try_catch_wrap = try_catch_wrap; + /** + */ + function try_catch_wrap_async(get_value) { + return (get_value() + .then((value) => Promise.resolve({ + "value": value, + "error": null, + })) + .catch((reason) => Promise.resolve({ + "value": null, + "error": reason, + }))); + } + call.try_catch_wrap_async = try_catch_wrap_async; + })(call = lib_plankton.call || (lib_plankton.call = {})); +})(lib_plankton || (lib_plankton = {})); +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +/* +This file is part of »bacterio-plankton:email«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:email« 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:email«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var email; + (function (email) { + /** + */ + function send(smtp_credentials, sender, receivers, subject, content) { + return __awaiter(this, void 0, void 0, function () { + var nm_nodemailer, transporter, info; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + nm_nodemailer = require("nodemailer"); + transporter = nm_nodemailer.createTransport({ + "host": smtp_credentials.host, + "port": smtp_credentials.port, + "secure": false, + "auth": { + "user": smtp_credentials.username, + "pass": smtp_credentials.password + }, + "debug": true + }); + return [4 /*yield*/, transporter.sendMail({ + "from": sender, + "to": receivers.join(", "), + "subject": subject, + "text": content + })]; + case 1: + info = _a.sent(); + return [2 /*return*/]; + } + }); + }); + } + email.send = send; + })(email = lib_plankton.email || (lib_plankton.email = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2024 '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 = {})); + ; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2024 '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 level_order(level1, level2) { + return (level1 <= level2); + } + log.level_order = level_order; + /** + */ + function level_show(level, _a) { + var _b = _a === void 0 ? {} : _a, _c = _b["abbreviated"], option_abbreviated = _c === void 0 ? false : _c; + if (option_abbreviated) { + switch (level) { + case log.enum_level.debug: return "DBG"; + case log.enum_level.info: return "INF"; + case log.enum_level.notice: return "NTC"; + case log.enum_level.warning: return "WRN"; + case log.enum_level.error: return "ERR"; + default: return "(unknown)"; + } + } + else { + switch (level) { + case log.enum_level.debug: return "debug"; + case log.enum_level.info: return "info"; + case log.enum_level.notice: return "notice"; + case log.enum_level.warning: return "warning"; + case log.enum_level.error: return "error"; + default: return "(unknown)"; + } + } + } + log.level_show = level_show; + /** + */ + function level_decode(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]; + } + log.level_decode = level_decode; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2024 '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) { + /** + * @todo use label + */ + function get_logger_logic(logger_data) { + return logger_data.map(function (channel_description) { return lib_plankton.log.get_channel_logic(channel_description); }); + } + log.get_logger_logic = get_logger_logic; + /** + */ + function format_entry(format_definition, entry) { + switch (format_definition.kind) { + case "jsonl": { + var now = Date.now(); + var timestamp = (now / 1000); + var datetime = (new Date(now)).toISOString(); + return (JSON.stringify({ + "datetime_timestamp": Math.round(timestamp), + "datetime_string": datetime /*.slice(0, 19)*/, + "level_numeric": entry.level, + "level_name": log.level_show(entry.level, { "abbreviated": false }), + "tags": entry.tags, + "incident": entry.incident, + "details": entry.details + }, undefined, (format_definition.data.structured + ? + "\t" + : + undefined))); + break; + } + case "human_readable": { + var parts = []; + parts.push(("<" + (new Date(Date.now())).toISOString() /*.slice(0, 19)*/ + ">")); + parts.push(("[" + log.level_show(entry.level, { "abbreviated": true }) + "]")); + for (var _i = 0, _a = entry.tags; _i < _a.length; _i++) { + var tag = _a[_i]; + parts.push(("{" + tag + "}")); + } + parts.push(entry.incident); + (entry.details !== null) && parts.push((": " + JSON.stringify(entry.details, undefined, undefined))); + return (parts.join(" ")); + break; + } + default: { + throw (new Error("unhandled format kind: " + format_definition["kind"])); + break; + } + } + } + log.format_entry = format_entry; + /** + */ + function parse_format_definition(format_definition_raw) { + return lib_plankton.call.distinguish((format_definition_raw !== null && format_definition_raw !== void 0 ? format_definition_raw : { + "kind": "human_readable", + "data": {} + }), { + "jsonl": function (_a) { + var structured = _a["structured"]; + return ({ + "kind": "jsonl", + "data": { + "structured": (structured !== null && structured !== void 0 ? structured : false) + } + }); + }, + "human_readable": function (data_) { return ({ + "kind": "human_readable", + "data": {} + }); } + }); + } + log.parse_format_definition = parse_format_definition; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2024 '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; + (function (channel) { + var filtered; + (function (filtered) { + /** + */ + function predicate_incident(substring) { + return (function (entry) { return entry.incident.includes(substring); }); + } + filtered.predicate_incident = predicate_incident; + /** + */ + function predicate_level(threshold) { + return (function (entry) { return log.level_order(threshold, entry.level); }); + } + filtered.predicate_level = predicate_level; + /** + */ + function predicate_tag(tag) { + return (function (entry) { return entry.tags.includes(tag); }); + } + filtered.predicate_tag = predicate_tag; + /** + * combines other predicates in disjunctive normal form + */ + function predicate_complex(definition) { + return (function (entry) { return definition.some(function (clause) { return clause.every(function (literal) { return (literal.item(entry) + === + literal.mode); }); }); }); + } + filtered.predicate_complex = predicate_complex; + /** + */ + function send(subject, entry) { + if (!subject.predicate(entry)) { + // do nothing + } + else { + subject.core.send(entry); + } + } + filtered.send = send; + /** + */ + function logic(subject) { + return { + "send": function (entry) { return send(subject, entry); } + }; + } + filtered.logic = logic; + })(filtered = channel.filtered || (channel.filtered = {})); + })(channel = log.channel || (log.channel = {})); + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2024 '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; + (function (channel) { + var minlevel; + (function (minlevel) { + /** + */ + function to_filter_subject(subject) { + return { + "core": subject.core, + "predicate": lib_plankton.log.channel.filtered.predicate_level(subject.threshold) + }; + } + /** + */ + function send(subject, entry) { + lib_plankton.log.channel.filtered.send(to_filter_subject(subject), entry); + } + minlevel.send = send; + /** + */ + function logic(subject) { + return { + "send": function (entry) { return send(subject, entry); } + }; + } + minlevel.logic = logic; + })(minlevel = channel.minlevel || (channel.minlevel = {})); + })(channel = log.channel || (log.channel = {})); + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2024 '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; + (function (channel) { + var std; + (function (std) { + /** + */ + function send(subject, entry) { + var write = lib_plankton.call.distinguish({ + "kind": subject.target, + "data": null + }, { + "stdout": function () { return function (x) { return process.stdout.write(x); }; }, + "stderr": function () { return function (x) { return process.stderr.write(x); }; } + }); + write(lib_plankton.log.format_entry(subject.format, entry) + + + "\n"); + } + std.send = send; + /** + */ + function logic(subject) { + return { + "send": function (entry) { return send(subject, entry); } + }; + } + std.logic = logic; + })(std = channel.std || (channel.std = {})); + })(channel = log.channel || (log.channel = {})); + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2024 '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; + (function (channel) { + var file; + (function (file) { + /** + */ + function send(subject, entry) { + var _this = this; + var nm_fs = require("fs"); + nm_fs.writeFile(subject.path, (lib_plankton.log.format_entry(subject.format, entry) + + + "\n"), { + "flag": "a+" + }, function (error) { + if (error !== null) { + process.stderr.write('-- [plankton] could not add log entry to file ' + _this.path + "\n"); + } + else { + // do nothing + } + }); + } + file.send = send; + /** + */ + function logic(subject) { + return { + "send": function (entry) { return send(subject, entry); } + }; + } + file.logic = logic; + })(file = channel.file || (channel.file = {})); + })(channel = log.channel || (log.channel = {})); + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2024 '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; + (function (channel) { + var notify; + (function (notify) { + /** + * @todo tags + */ + function send(subject, entry) { + var nm_child_process = require("child_process"); + var command = ("notify-send" + + + " " + + + ("'" + + + ("[" + log.level_show(entry.level) + "]") + + + " " + + + entry.incident + + + "'") + + + " " + + + ("'" + + + JSON.stringify(entry.details) + + + "'")); + nm_child_process.exec(command, function (error, stdout, stderr) { + // do noting + }); + } + notify.send = send; + /** + */ + function logic(subject) { + return { + "send": function (entry) { return send(subject, entry); } + }; + } + notify.logic = logic; + })(notify = channel.notify || (channel.notify = {})); + })(channel = log.channel || (log.channel = {})); + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2024 '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; + (function (channel) { + var email; + (function (email) { + /** + * @todo tags + */ + function send(subject, entry) { + var nm_fs = require("fs"); + lib_plankton.email.send(subject.smtp_credentials, subject.sender, subject.receivers, (("[" + log.level_show(entry.level) + "]") + + + " " + + + ("" + entry.incident + "")), JSON.stringify(entry.details, undefined, " ")); + } + email.send = send; + /** + */ + function logic(subject) { + return { + "send": function (entry) { return send(subject, entry); } + }; + } + email.logic = logic; + })(email = channel.email || (channel.email = {})); + })(channel = log.channel || (log.channel = {})); + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2024 '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 get_channel_logic(channel_description) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j; + switch (channel_description.kind) { + default: { + throw (new Error("unhandled log channel kind: " + channel_description.kind)); + break; + } + case "filtered": { + return lib_plankton.log.channel.filtered.logic({ + "core": get_channel_logic(channel_description.data.core), + "predicate": lib_plankton.log.channel.filtered.predicate_complex(channel_description.data.predicate.map(function (clause_raw) { return clause_raw.map(function (literal_raw) { + var _a; + return ({ + "mode": ((_a = literal_raw["mode"]) !== null && _a !== void 0 ? _a : true), + "item": lib_plankton.call.distinguish(literal_raw["item"], { + "incident": function (_a) { + var substring = _a["substring"]; + if (substring === undefined) { + throw (new Error("required parameter missing: substring")); + } + else { + return lib_plankton.log.channel.filtered.predicate_incident(substring); + } + }, + "level": function (_a) { + var threshold = _a["threshold"]; + if (threshold === undefined) { + throw (new Error("required parameter missing: threshold")); + } + else { + return lib_plankton.log.channel.filtered.predicate_level(log.level_decode(threshold)); + } + }, + "tag": function (_a) { + var value = _a["value"]; + if (value === undefined) { + throw (new Error("required parameter missing: value")); + } + else { + return lib_plankton.log.channel.filtered.predicate_tag(value); + } + } + }, { + "fallback": function () { return function (entry) { return true; }; } + }) + }); + }); })) + }); + break; + } + case "minlevel": { + return lib_plankton.log.channel.minlevel.logic({ + "core": get_channel_logic(channel_description.data.core), + "threshold": log.level_decode(channel_description.data.threshold) + }); + break; + } + case "std": { + return lib_plankton.log.channel.std.logic({ + "target": ((_b = (_a = channel_description === null || channel_description === void 0 ? void 0 : channel_description.data) === null || _a === void 0 ? void 0 : _a.target) !== null && _b !== void 0 ? _b : "stdout"), + "format": log.parse_format_definition((_c = channel_description === null || channel_description === void 0 ? void 0 : channel_description.data) === null || _c === void 0 ? void 0 : _c.format) + }); + break; + } + case "file": { + /** + * @todo exceptions on missing parameters + */ + return lib_plankton.log.channel.file.logic({ + "path": ((_e = (_d = channel_description === null || channel_description === void 0 ? void 0 : channel_description.data) === null || _d === void 0 ? void 0 : _d.path) !== null && _e !== void 0 ? _e : "log"), + "format": log.parse_format_definition((_f = channel_description === null || channel_description === void 0 ? void 0 : channel_description.data) === null || _f === void 0 ? void 0 : _f.format) + }); + break; + } + case "notify": { + return lib_plankton.log.channel.notify.logic({}); + break; + } + case "email": { + /** + * @todo exceptions on missing parameters + */ + return lib_plankton.log.channel.email.logic({ + "smtp_credentials": channel_description.data.smtp_credentials, + "sender": ((_h = (_g = channel_description.data) === null || _g === void 0 ? void 0 : _g.sender) !== null && _h !== void 0 ? _h : "plankton"), + "receivers": (_j = channel_description.data) === null || _j === void 0 ? void 0 : _j.receivers + }); + break; + } + } + } + log.get_channel_logic = get_channel_logic; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2024 '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 default_logger() { + return [ + { + "kind": "minlevel", + "data": { + "core": { + "kind": "std", + "data": { + "target": "stdout", + "format": { + "kind": "human_readable", + "data": {} + } + } + }, + "threshold": "info" + } + }, + ]; + } + log.default_logger = default_logger; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2024 '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 _main_logger_data = null; + /** + */ + function set_main_logger(logger_data) { + _main_logger_data = logger_data; + } + log.set_main_logger = set_main_logger; + /** + */ + function get_main_logger() { + return (_main_logger_data !== null && _main_logger_data !== void 0 ? _main_logger_data : log.default_logger()); + } + /** + */ + function get_main_logger_logic() { + return lib_plankton.log.get_logger_logic(get_main_logger()); + } + /** + * consumes a log entry, i.e. sends it to all channels + */ + function send_(logger, entry) { + logger.forEach(function (channel) { return channel.send(entry); }); + } + log.send_ = send_; + /** + * [convenience] + * + * @todo rename to "send" + */ + function debug_(logger, incident, _a) { + var _b = _a === void 0 ? {} : _a, _c = _b["tags"], option_tags = _c === void 0 ? [] : _c, _d = _b["details"], option_details = _d === void 0 ? null : _d; + send_(logger, { + "level": log.enum_level.debug, + "incident": incident, + "tags": option_tags, + "details": option_details + }); + } + log.debug_ = debug_; + /** + * [convenience] + * + * @todo rename to "info" + */ + function info_(logger, incident, _a) { + var _b = _a === void 0 ? {} : _a, _c = _b["tags"], option_tags = _c === void 0 ? [] : _c, _d = _b["details"], option_details = _d === void 0 ? null : _d; + send_(logger, { + "level": log.enum_level.info, + "incident": incident, + "tags": option_tags, + "details": option_details + }); + } + log.info_ = info_; + /** + * [convenience] + * + * @todo rename to "notice" + */ + function notice_(logger, incident, _a) { + var _b = _a === void 0 ? {} : _a, _c = _b["tags"], option_tags = _c === void 0 ? [] : _c, _d = _b["details"], option_details = _d === void 0 ? null : _d; + send_(logger, { + "level": log.enum_level.notice, + "incident": incident, + "tags": option_tags, + "details": option_details + }); + } + log.notice_ = notice_; + /** + * [convenience] + * + * @todo rename to "warning" + */ + function warning_(logger, incident, _a) { + var _b = _a === void 0 ? {} : _a, _c = _b["tags"], option_tags = _c === void 0 ? [] : _c, _d = _b["details"], option_details = _d === void 0 ? null : _d; + send_(logger, { + "level": log.enum_level.warning, + "incident": incident, + "tags": option_tags, + "details": option_details + }); + } + log.warning_ = warning_; + /** + * [convenience] + * + * @todo rename to "error" + */ + function error_(logger, incident, _a) { + var _b = _a === void 0 ? {} : _a, _c = _b["tags"], option_tags = _c === void 0 ? [] : _c, _d = _b["details"], option_details = _d === void 0 ? null : _d; + send_(logger, { + "level": log.enum_level.error, + "incident": incident, + "tags": option_tags, + "details": option_details + }); + } + log.error_ = error_; + /** + * [convenience] + */ + function _send(entry) { + send_(get_main_logger_logic(), entry); + } + log._send = _send; + /** + * [convenience] + */ + function _debug(incident, _a) { + var _b = _a === void 0 ? {} : _a, _c = _b["tags"], option_tags = _c === void 0 ? [] : _c, _d = _b["details"], option_details = _d === void 0 ? null : _d; + debug_(get_main_logger_logic(), incident, { + "tags": option_tags, + "details": option_details + }); + } + log._debug = _debug; + /** + * [convenience] + */ + function _info(incident, _a) { + var _b = _a === void 0 ? {} : _a, _c = _b["tags"], option_tags = _c === void 0 ? [] : _c, _d = _b["details"], option_details = _d === void 0 ? null : _d; + info_(get_main_logger_logic(), incident, { + "tags": option_tags, + "details": option_details + }); + } + log._info = _info; + /** + * [convenience] + */ + function _notice(incident, _a) { + var _b = _a === void 0 ? {} : _a, _c = _b["tags"], option_tags = _c === void 0 ? [] : _c, _d = _b["details"], option_details = _d === void 0 ? null : _d; + notice_(get_main_logger_logic(), incident, { + "tags": option_tags, + "details": option_details + }); + } + log._notice = _notice; + /** + * [convenience] + */ + function _warning(incident, _a) { + var _b = _a === void 0 ? {} : _a, _c = _b["tags"], option_tags = _c === void 0 ? [] : _c, _d = _b["details"], option_details = _d === void 0 ? null : _d; + warning_(get_main_logger_logic(), incident, { + "tags": option_tags, + "details": option_details + }); + } + log._warning = _warning; + /** + * [convenience] + */ + function _error(incident, _a) { + var _b = _a === void 0 ? {} : _a, _c = _b["tags"], option_tags = _c === void 0 ? [] : _c, _d = _b["details"], option_details = _d === void 0 ? null : _d; + error_(get_main_logger_logic(), incident, { + "tags": option_tags, + "details": option_details + }); + } + log._error = _error; + /** + * [convenience] + * + * @deprecated use ._debug instead! + */ + function debug(incident, details, tags) { + if (details === void 0) { details = null; } + if (tags === void 0) { tags = []; } + _debug(incident, { + "details": details, + "tags": tags + }); + } + log.debug = debug; + /** + * [convenience] + * + * @deprecated use ._info instead! + */ + function info(incident, details, tags) { + if (details === void 0) { details = null; } + if (tags === void 0) { tags = []; } + _info(incident, { + "details": details, + "tags": tags + }); + } + log.info = info; + /** + * [convenience] + * + * @deprecated use ._notice instead! + */ + function notice(incident, details, tags) { + if (details === void 0) { details = null; } + if (tags === void 0) { tags = []; } + _notice(incident, { + "details": details, + "tags": tags + }); + } + log.notice = notice; + /** + * [convenience] + * + * @deprecated use ._warning instead! + */ + function warning(incident, details, tags) { + if (details === void 0) { details = null; } + if (tags === void 0) { tags = []; } + _warning(incident, { + "details": details, + "tags": tags + }); + } + log.warning = warning; + /** + * [convenience] + * + * @deprecated use ._error instead! + */ + function error(incident, details, tags) { + if (details === void 0) { details = null; } + if (tags === void 0) { tags = []; } + _error(incident, { + "details": details, + "tags": tags + }); + } + log.error = error; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:string«. + +Copyright 2016-2024 '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-2024 '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) { + lib_plankton.log.error("plankton.string.generate.out_of_valid_indices", null); + throw (new Error("[string_generate] out of valid indices")); + } + else { + return string.sprintf(prefix + "%0" + hexdigits.toString() + "X", [index_is++]); + } + } + string.generate = generate; + /** + * @author fenris + */ + function join(parts, glue = " ") { + if (parts.length == 0) { + return ""; + } + else { + return parts.join(glue); + } + } + string.join = join; + /** + * @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 + * @deprecated use limit + */ + function cut(str, length, delimiter = "…") { + if (str.length <= length) { + return str; + } + else { + return (str.slice(0, length - delimiter.length) + delimiter); + } + } + string.cut = cut; + /** + */ + function limit(str, options = {}) { + options = Object.assign({ + "length": 120, + "indicator": "…", + }, options); + return ((str.length <= options.length) + ? str + : (str.slice(0, options.length - options.indicator.length) + options.indicator)); + } + string.limit = limit; + /** + */ + function slice(str, size) { + let slices = []; + let rest = str; + while (rest.length > 0) { + slices.push(rest.slice(0, size)); + rest = rest.slice(size); + } + return slices; + } + string.slice = slice; + /** + */ + function capitalize(str) { + return (str[0].toUpperCase() + str.slice(1)); + } + string.capitalize = capitalize; + })(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-2024 '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-2024 '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:pit«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:pit« 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:pit« 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:pit«. If not, see . + */ +/* +This file is part of »bacterio-plankton:pit«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:pit« 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:pit« 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:pit«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var pit; + (function (pit_1) { + /** + * @todo complete + */ + function timezone_name_to_timezone_shift(timezone_name) { + const map = { + "UTC": 0, + "CET": +1, + "CEST": +2, + }; + if (!(timezone_name in map)) { + throw (new Error("unhandled timezone: " + timezone_name)); + } + else { + return map[timezone_name]; + } + } + pit_1.timezone_name_to_timezone_shift = timezone_name_to_timezone_shift; + /** + */ + function date_object_get_week_of_year(date) { + let date_ = new Date(date.getTime()); + date_.setHours(0, 0, 0, 0); + // Thursday in current week decides the year. + date_.setDate(date_.getDate() + 3 - (date_.getDay() + 6) % 7); + // January 4 is always in week 1. + let week1 = new Date(date_.getFullYear(), 0, 4); + // Adjust to Thursday in week 1 and count number of weeks from date to week1. + return (1 + + + Math.round((((date_.getTime() - week1.getTime()) / 86400000) + - + 3 + + + (week1.getDay() + 6) % 7) + / + 7)); + } + pit_1.date_object_get_week_of_year = date_object_get_week_of_year; + /** + */ + function to_unix_timestamp(pit) { + return pit; + } + pit_1.to_unix_timestamp = to_unix_timestamp; + /** + */ + function from_unix_timestamp(unix_timestamp) { + return unix_timestamp; + } + pit_1.from_unix_timestamp = from_unix_timestamp; + /** + */ + function to_date_object(pit) { + return (new Date(pit * 1000)); + } + pit_1.to_date_object = to_date_object; + /** + */ + function from_date_object(date_object) { + return Math.round(date_object.getTime() / 1000); + } + /** + * @todo test + */ + function to_datetime(pit, { "timezone_shift": option_timezone_shift = 0, } = {}) { + return lib_plankton.call.convey(pit, [ + to_date_object, + (x) => x.getTime(), + (x) => (x + ((option_timezone_shift * (60 * 60)) * 1000)), + (x) => new Date(x), + x => x.toISOString(), + x => ({ + "timezone_shift": option_timezone_shift, + "date": { + "year": parseInt(x.slice(0, 4)), + "month": parseInt(x.slice(5, 7)), + "day": parseInt(x.slice(8, 10)), + }, + "time": { + "hour": parseInt(x.slice(11, 13)), + "minute": parseInt(x.slice(14, 16)), + "second": parseInt(x.slice(17, 19)), + }, + }) + ]); + } + pit_1.to_datetime = to_datetime; + /** + */ + function from_datetime(datetime) { + return lib_plankton.call.convey(datetime, [ + (x) => lib_plankton.string.coin("{{year}}-{{month}}-{{day}}T{{hour}}:{{minute}}:{{second}}.000+{{shift}}", { + "year": x.date.year.toFixed(0).padStart(4, "0"), + "month": x.date.month.toFixed(0).padStart(2, "0"), + "day": x.date.day.toFixed(0).padStart(2, "0"), + "hour": ((x.time !== null) ? x.time.hour : 0).toFixed(0).padStart(2, "0"), + "minute": ((x.time !== null) ? x.time.minute : 0).toFixed(0).padStart(2, "0"), + "second": ((x.time !== null) ? x.time.second : 0).toFixed(0).padStart(2, "0"), + "shift": (x.timezone_shift.toFixed(0).padStart(2, "0") + ":00"), + }), + x => (new Date(x)), + from_date_object, + ]); + } + pit_1.from_datetime = from_datetime; + /** + */ + function is_before(pit, reference) { + return (pit < reference); + } + pit_1.is_before = is_before; + /** + */ + function is_after(pit, reference) { + return (pit > reference); + } + /** + */ + function is_between(pit, reference_left, reference_right) { + return (is_after(pit, reference_left) + && + is_before(pit, reference_right)); + } + pit_1.is_between = is_between; + /** + */ + function shift_hour(pit, increment) { + return (pit + (60 * 60 * increment)); + } + pit_1.shift_hour = shift_hour; + /** + */ + function shift_day(pit, increment) { + return (pit + (60 * 60 * 24 * increment)); + } + pit_1.shift_day = shift_day; + /** + */ + function shift_week(pit, increment) { + return (pit + (60 * 60 * 24 * 7 * increment)); + } + pit_1.shift_week = shift_week; + /** + */ + function shift_year(pit, increment) { + return (pit + (60 * 60 * 24 * 365 * increment)); + } + /** + */ + function trunc_minute(pit) { + const datetime_input = to_datetime(pit); + const datetime_output = { + "timezone_shift": 0, + "date": { + "year": datetime_input.date.year, + "month": datetime_input.date.month, + "day": datetime_input.date.day, + }, + "time": { + "hour": ((datetime_input.time === null) + ? + 0 + : + datetime_input.time.hour), + "minute": ((datetime_input.time === null) + ? + 0 + : + datetime_input.time.minute), + "second": 0, + }, + }; + return from_datetime(datetime_output); + } + /** + */ + function trunc_hour(pit) { + const datetime_input = to_datetime(pit); + const datetime_output = { + "timezone_shift": 0, + "date": { + "year": datetime_input.date.year, + "month": datetime_input.date.month, + "day": datetime_input.date.day, + }, + "time": { + "hour": ((datetime_input.time === null) + ? + 0 + : + datetime_input.time.hour), + "minute": 0, + "second": 0, + }, + }; + return from_datetime(datetime_output); + } + /** + */ + function trunc_day(pit) { + const datetime_input = to_datetime(pit); + const datetime_output = { + "timezone_shift": 0, + "date": { + "year": datetime_input.date.year, + "month": datetime_input.date.month, + "day": datetime_input.date.day, + }, + "time": { + "hour": 0, + "minute": 0, + "second": 0, + }, + }; + return from_datetime(datetime_output); + } + /** + */ + function trunc_week(pit) { + const date_object = to_date_object(pit); + return lib_plankton.call.convey(date_object.getDay(), [ + (x) => ((x === 0) ? 7 : x), + (x) => (x - 1), + (x) => shift_day(pit, (-x)), + trunc_day + ]); + } + pit_1.trunc_week = trunc_week; + /** + */ + function trunc_month(pit) { + const datetime_input = to_datetime(pit); + const datetime_output = { + "timezone_shift": 0, + "date": { + "year": datetime_input.date.year, + "month": datetime_input.date.month, + "day": 1, + }, + "time": { + "hour": 0, + "minute": 0, + "second": 0, + }, + }; + return from_datetime(datetime_output); + } + /** + */ + function trunc_year(pit) { + const datetime_input = to_datetime(pit); + const datetime_output = { + "timezone_shift": 0, + "date": { + "year": datetime_input.date.year, + "month": 1, + "day": 1, + }, + "time": { + "hour": 0, + "minute": 0, + "second": 0, + }, + }; + return from_datetime(datetime_output); + } + /** + */ + function now() { + return from_date_object(new Date(Date.now())); + } + pit_1.now = now; + /** + * @param year year according to specified timezone shift + * @param week week according to specified timezone shift + * @return the begin of the week (monday, 00:00) + */ + function from_ywd(ywd, { "timezone_shift": option_timezone_shift = 0, } = {}) { + return lib_plankton.call.convey({ + "timezone_shift": option_timezone_shift, + "date": { + "year": ywd.year, + "month": 1, + "day": 1, + }, + "time": { + "hour": 0, + "minute": 0, + "second": 0 + } + }, [ + from_datetime, + (x) => shift_week(x, (ywd.week - 1)), + trunc_week, + (x) => shift_day(x, (ywd.day - 1)), + ]); + } + pit_1.from_ywd = from_ywd; + /** + * @todo timezone + */ + function to_ywd(pit, { "timezone_shift": option_timezone_shift = 0, } = {}) { + return lib_plankton.call.convey(pit, [ + to_date_object, + x => ({ + "year": x.getFullYear(), + "week": date_object_get_week_of_year(x), + "day": ((day => (day <= 0) ? 7 : day)(x.getDay())), + }) + ]); + } + pit_1.to_ywd = to_ywd; + /** + * computes the point in time for switching to central european summer time + * + * @todo write tests + */ + function cest_switch_on(year) { + return lib_plankton.call.convey(year, [ + (x) => ({ + "timezone_shift": 0, + "date": { + "year": x, + "month": 4, + "day": 1, + }, + "time": { + "hour": 2, + "minute": 0, + "second": 0 + }, + }), + from_datetime, + trunc_week, + x => shift_day(x, -1), + ]); + } + pit_1.cest_switch_on = cest_switch_on; + /** + * computes the point in time for switching away from central european summer time + * + * @todo write tests + */ + function cest_switch_off(year) { + return lib_plankton.call.convey(year, [ + (x) => ({ + "timezone_shift": 0, + "date": { + "year": x, + "month": 11, + "day": 1, + }, + "time": { + "hour": 1, + "minute": 0, + "second": 0 + }, + }), + from_datetime, + trunc_week, + x => shift_day(x, -1), + ]); + } + pit_1.cest_switch_off = cest_switch_off; + /** + */ + function timezone_shift_ce(pit) { + const year = to_datetime(pit).date.year; + return (is_between(pit, cest_switch_on(year), cest_switch_off(year)) + ? +2 + : +1); + } + pit_1.timezone_shift_ce = timezone_shift_ce; + /** + * [convenience] + */ + function to_datetime_ce(pit) { + return to_datetime(pit, { + "timezone_shift": timezone_shift_ce(pit), + }); + } + pit_1.to_datetime_ce = to_datetime_ce; + /** + */ + function datetime_translate(datetime, timezone_shift) { + if (datetime.timezone_shift === timezone_shift) { + return datetime; + } + else { + const pit = from_datetime(datetime); + const pit_shifted = shift_hour(pit, (timezone_shift - datetime.timezone_shift)); + const datetime_shifted = to_datetime(pit_shifted); + return { + "timezone_shift": timezone_shift, + "date": datetime_shifted.date, + "time": ((datetime.time === null) + ? + null + : datetime_shifted.time) + }; + } + } + pit_1.datetime_translate = datetime_translate; + /** + * [convenience] + */ + function datetime_translate_ce(datetime) { + return datetime_translate(datetime, timezone_shift_ce(from_datetime(datetime))); + } + pit_1.datetime_translate_ce = datetime_translate_ce; + /** + */ + function timezone_shift_format(timezone_shift) { + return lib_plankton.string.coin("{{sign}}{{value}}", { + "sign": ((timezone_shift === 0) + ? + " " + : + ((timezone_shift > 0) + ? + "+" + : + "-")), + "value": Math.abs(timezone_shift).toFixed(0), + }); + } + pit_1.timezone_shift_format = timezone_shift_format; + /** + */ + function date_format(date) { + return lib_plankton.string.coin("{{year}}-{{month}}-{{day}}", { + "year": date.year.toFixed(0).padStart(4, "0"), + "month": date.month.toFixed(0).padStart(2, "0"), + "day": date.day.toFixed(0).padStart(2, "0"), + }); + } + pit_1.date_format = date_format; + /** + */ + function time_format(time, { "show_seconds": option_show_seconds = false, } = {}) { + return lib_plankton.string.coin((option_show_seconds + ? + "{{hour}}:{{minute}}:{{seconds}}" + : + "{{hour}}:{{minute}}"), { + "hour": time.hour.toFixed(0).padStart(2, "0"), + "minute": time.minute.toFixed(0).padStart(2, "0"), + "second": time.second.toFixed(0).padStart(2, "0"), + }); + } + pit_1.time_format = time_format; + /** + * @todo show timezone + */ + function datetime_format(datetime, { "timezone_indicator": option_timezone_indicator = "", "show_timezone": option_show_timezone = false, "adjust_to_ce": option_adjust_to_ce = false, "omit_date": option_omit_date = false, } = {}) { + if (datetime === null) { + return "-"; + } + else { + const datetime_adjusted = (option_adjust_to_ce + ? + to_datetime_ce(from_datetime(datetime)) + : + datetime); + return lib_plankton.string.coin("{{macro_date_and_time}}{{macro_timezone}}", { + "macro_date_and_time": ([ + // date + (option_omit_date + ? + null + : + date_format(datetime_adjusted.date)), + // time + ((datetime_adjusted.time === null) + ? + null + : + time_format(datetime_adjusted.time)), + ] + .filter(x => (x !== null)) + .join(", ")), + "macro_timezone": (option_show_timezone + ? + lib_plankton.string.coin(" [{{timezone_indicator}}{{timezone_value}}]", { + "timezone_indicator": option_timezone_indicator, + "timezone_value": timezone_shift_format(datetime_adjusted.timezone_shift), + }) + : + ""), + }); + } + } + pit_1.datetime_format = datetime_format; + /** + */ + function timespan_format(from, to, { "timezone_indicator": option_timezone_indicator = "", "show_timezone": option_show_timezone = false, "adjust_to_ce": option_adjust_to_ce = false, "omit_date": option_omit_date = false, } = {}) { + const from_adjusted = (option_adjust_to_ce + ? + datetime_translate_ce(from) + : + from); + const to_adjusted = ((to === null) + ? + null + : + (option_adjust_to_ce + ? + datetime_translate_ce(to) + : + to)); + return lib_plankton.string.coin("{{from}}{{to_macro}}{{macro_timezone}}", { + "from": datetime_format(from_adjusted, { + "show_timezone": false, + "adjust_to_ce": false, + "omit_date": option_omit_date, + }), + "to_macro": ((to_adjusted === null) + ? + "" + : + lib_plankton.string.coin(" - {{to}}", { + "to": datetime_format(to_adjusted, { + "omit_date": ((from_adjusted.date.year === to_adjusted.date.year) + && + (from_adjusted.date.month === to_adjusted.date.month) + && + (from_adjusted.date.day === to_adjusted.date.day)) + }), + })), + "macro_timezone": (option_show_timezone + ? + lib_plankton.string.coin(" [{{timezone_indicator}}{{timezone_value}}]", { + "timezone_indicator": option_timezone_indicator, + "timezone_value": timezone_shift_format(from_adjusted.timezone_shift), + }) + : + ""), + }); + } + pit_1.timespan_format = timespan_format; + })(pit = lib_plankton.pit || (lib_plankton.pit = {})); +})(lib_plankton || (lib_plankton = {})); +"use strict"; +/* +This file is part of »bacterio-plankton:http_base«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:http_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:http_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:http_base«. If not, see . + */ +/* +This file is part of »bacterio-plankton:http_base«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:http_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:http_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:http_base«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var http_base; + (function (http_base) { + /** + */ + const linebreak = "\r\n"; + /** + */ + function capitalize_all(str) { + return str.split("-").map(x => lib_plankton.string.capitalize(x)).join("-"); + } + /** + */ + function encode_request(encode_method, request) { + let request_raw = ""; + request_raw += lib_plankton.string.coin("{{method}} {{path}}{{query}} {{version}}{{linebreak}}", { + "method": encode_method(request.method), + "path": request.path, + "query": ((request.query === null) ? "" : request.query), + "version": request.version, + "linebreak": linebreak, + }); + if (request.host === null) { + // do nothing + } + else { + request_raw += lib_plankton.string.coin("Host: {{host}}{{linebreak}}", { + "host": request.host, + "linebreak": linebreak, + }); + } + for (const [key, value] of Object.entries(request.headers)) { + request_raw += lib_plankton.string.coin("{{key}}: {{value}}{{linebreak}}", { + "key": capitalize_all(key), + "value": value, + "linebreak": linebreak, + }); + } + request_raw += linebreak; + if (request.body === null) { + // do nothing + } + else { + request_raw += request.body.toString(); + } + return request_raw; + } + http_base.encode_request = encode_request; + /** + */ + function decode_request(decode_method, has_body, request_raw) { + const lines = lib_plankton.string.split(request_raw, linebreak); + if (lines.length <= 0) { + throw (new Error("malformed request")); + } + else { + const first = lines[0]; + lines.shift(); + const parts = first.split(" "); + const method = decode_method(parts[0]); + const path_and_query = parts[1]; + const parts_ = path_and_query.split("?"); + const path = parts_[0]; + const query = ((parts_.length <= 1) ? null : ("?" + parts_.slice(1).join("?"))); + const version = parts[2]; + let headers = {}; + while (true) { + const line = lines[0]; + lines.shift(); + if (line === "") { + break; + } + else { + const [key, value] = line.split(": ", 2); + headers[key.toLowerCase()] = value; + } + } + const body = (has_body(method) + // @ts-ignore + ? Buffer.from(lines.join(linebreak)) + : null); + const request = { + // TODO + "scheme": "http", + "host": (headers["host"] ?? null), + "path": path, + "version": version, + "method": method, + "query": query, + "headers": headers, + "body": body, + }; + return request; + } + } + http_base.decode_request = decode_request; + /** + */ + function encode_response(encode_status_code, get_status_text, response) { + let response_raw = ""; + response_raw += lib_plankton.string.coin("{{version}} {{status_code}} {{status_text}}{{linebreak}}", { + "version": (response.version ?? ""), + "status_code": encode_status_code(response.status_code), + "status_text": get_status_text(response.status_code), + "linebreak": linebreak, + }); + for (const [key, value] of Object.entries(response.headers)) { + response_raw += lib_plankton.string.coin("{{key}}: {{value}}{{linebreak}}", { + "key": capitalize_all(key), + "value": value, + "linebreak": linebreak, + }); + } + response_raw += linebreak; + if (response.body === null) { + // do nothing + } + else { + response_raw += response.body.toString(); + } + return response_raw; + } + http_base.encode_response = encode_response; + /** + */ + function decode_response(decode_status_code, response_raw) { + const lines = response_raw.split(linebreak); + const first = lines[0]; + lines.shift(); + const first_parts = first.split(" "); + const version = first_parts[0]; + const status_code = decode_status_code(first_parts[1]); + // first_parts.slice(2) ? probably irrelevant + let headers = {}; + while (true) { + const line = lines[0]; + lines.shift(); + if (line === "") { + break; + } + else { + const [key, value] = line.split(": ", 2); + headers[key.toLowerCase()] = value; + } + } + // @ts-ignore + const body = Buffer.from(lines.join(linebreak)); + const response = { + // TODO + "version": version, + "status_code": status_code, + "headers": headers, + "body": body, + }; + return response; + } + http_base.decode_response = decode_response; + /** + * executes an HTTP request + * + * @todo define type_signal + */ + async function call(has_body, encode_method, decode_status_code, request, { "timeout": option_timeout = 5.0, "follow_redirects": option_follow_redirects = false, "implementation": option_implementation = "fetch", } = {}) { + const target = lib_plankton.string.coin("{{scheme}}://{{host}}{{path}}{{query}}", { + "scheme": request.scheme, + "host": (request.host ?? ""), + "path": request.path, + "query": (request.query ?? ""), + }); + switch (option_implementation) { + default: { + return Promise.reject(new Error("invalid implementation: " + option_implementation)); + break; + } + case "fetch": { + function core(signal) { + return (fetch(target, Object.assign({ + "method": encode_method(request.method), + "headers": request.headers, + /* + "redirect": ( + option_follow_redirects + ? + "follow" + : + "manual" + ), + */ + "signal": (signal + ?? + undefined), + // "keepalive": false, + }, ((has_body(request.method) + && + (request.body !== null)) + ? { + "body": request.body.toString(), + } + : {}))) + .catch((reason) => { + // console.info(reason); + return Promise.reject(reason); + }) + .then((response_raw) => (response_raw.text() + .then((body) => Promise.resolve({ + // TODO + "version": null, + "status_code": decode_status_code(response_raw.status.toFixed(0)), + "headers": ((headers_raw => { + let headers = {}; + headers_raw.forEach((value, key) => { + headers[key] = value; + }); + return headers; + })(response_raw.headers)), + "body": body, + }))))); + } + function timeout(controller) { + return (new Promise((resolve, reject) => { + if (option_timeout === null) { + // do nothing (neither resolve nor reject ever) + } + else { + setTimeout(() => { + controller.abort(); + resolve(null); + }, (option_timeout * 1000)); + } + })); + } + const controller = new AbortController(); + const signal = controller.signal; + const response = await Promise.race([ + timeout(controller), + core(signal), + ]); + if (response === null) { + throw (new Error("http_request_timeout")); + } + else { + return response; + } + break; + } + case "http_module": { + // @ts-ignore + const nm_http = require("http"); + // @ts-ignore + const nm_https = require("https"); + return (new Promise((resolve, reject) => { + const req = ((request.scheme === "https") + ? nm_https + : nm_http) + .request(target, { + "method": request.method, + "headers": request.headers, + }, + // @ts-ignore + (res) => { + try { + let response_body = ""; + res.setEncoding("utf8"); + res.on("data", (chunk) => { + response_body += chunk; + }); + res.on("end", () => { + resolve({ + // TODO + "version": null, + "status_code": res.statusCode, + "headers": res.headers, + "body": response_body, + }); + }); + } + catch (error) { + reject(error); + } + }); + req.on("error", (error) => { + reject(error); + }); + req.write(request.body); + req.end(); + })); + break; + } + } + } + http_base.call = call; + })(http_base = lib_plankton.http_base || (lib_plankton.http_base = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:http«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:http« 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:http« 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:http«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var http; + (function (http) { + /** + * @author fenris + */ + let enum_method; + (function (enum_method) { + enum_method["options"] = "options"; + enum_method["head"] = "head"; + enum_method["get"] = "get"; + enum_method["delete"] = "delete"; + enum_method["post"] = "post"; + enum_method["put"] = "put"; + enum_method["patch"] = "patch"; + })(enum_method = http.enum_method || (http.enum_method = {})); + /** + */ + let enum_status_code; + (function (enum_status_code) { + enum_status_code[enum_status_code["continue_"] = 100] = "continue_"; + enum_status_code[enum_status_code["switching_protocols"] = 101] = "switching_protocols"; + enum_status_code[enum_status_code["early_hints"] = 103] = "early_hints"; + enum_status_code[enum_status_code["ok"] = 200] = "ok"; + enum_status_code[enum_status_code["created"] = 201] = "created"; + enum_status_code[enum_status_code["accepted"] = 202] = "accepted"; + enum_status_code[enum_status_code["non_authoritative_information"] = 203] = "non_authoritative_information"; + enum_status_code[enum_status_code["no_content"] = 204] = "no_content"; + enum_status_code[enum_status_code["reset_content"] = 205] = "reset_content"; + enum_status_code[enum_status_code["partial_coentent"] = 206] = "partial_coentent"; + enum_status_code[enum_status_code["multiple_choices"] = 300] = "multiple_choices"; + enum_status_code[enum_status_code["moved_permanently"] = 301] = "moved_permanently"; + enum_status_code[enum_status_code["found"] = 302] = "found"; + enum_status_code[enum_status_code["see_other"] = 303] = "see_other"; + enum_status_code[enum_status_code["not_modified"] = 304] = "not_modified"; + enum_status_code[enum_status_code["temporary_redirect"] = 307] = "temporary_redirect"; + enum_status_code[enum_status_code["permanent_redirect"] = 308] = "permanent_redirect"; + enum_status_code[enum_status_code["bad_request"] = 400] = "bad_request"; + enum_status_code[enum_status_code["unauthorized"] = 401] = "unauthorized"; + enum_status_code[enum_status_code["payment_required"] = 402] = "payment_required"; + enum_status_code[enum_status_code["forbidden"] = 403] = "forbidden"; + enum_status_code[enum_status_code["not_found"] = 404] = "not_found"; + enum_status_code[enum_status_code["method_not_allowed"] = 405] = "method_not_allowed"; + enum_status_code[enum_status_code["not_acceptable"] = 406] = "not_acceptable"; + enum_status_code[enum_status_code["proxy_authentication_required"] = 407] = "proxy_authentication_required"; + enum_status_code[enum_status_code["request_timeout"] = 408] = "request_timeout"; + enum_status_code[enum_status_code["conflict"] = 409] = "conflict"; + enum_status_code[enum_status_code["gone"] = 410] = "gone"; + enum_status_code[enum_status_code["length_required"] = 411] = "length_required"; + enum_status_code[enum_status_code["precondition_failed"] = 412] = "precondition_failed"; + enum_status_code[enum_status_code["payload_too_large"] = 413] = "payload_too_large"; + enum_status_code[enum_status_code["uri_too_long"] = 414] = "uri_too_long"; + enum_status_code[enum_status_code["unsupported_media_type"] = 415] = "unsupported_media_type"; + enum_status_code[enum_status_code["range_not_satisfiable"] = 416] = "range_not_satisfiable"; + enum_status_code[enum_status_code["expectation_failed"] = 417] = "expectation_failed"; + enum_status_code[enum_status_code["i_m_a_teapot"] = 418] = "i_m_a_teapot"; + enum_status_code[enum_status_code["unprocessable_entity"] = 422] = "unprocessable_entity"; + enum_status_code[enum_status_code["too_early"] = 425] = "too_early"; + enum_status_code[enum_status_code["upgrade_required"] = 426] = "upgrade_required"; + enum_status_code[enum_status_code["precondition_required"] = 428] = "precondition_required"; + enum_status_code[enum_status_code["too_many_requests"] = 429] = "too_many_requests"; + enum_status_code[enum_status_code["request_header_fields_too_large"] = 431] = "request_header_fields_too_large"; + enum_status_code[enum_status_code["unavailable_for_legal_reasons"] = 451] = "unavailable_for_legal_reasons"; + enum_status_code[enum_status_code["internal_server_error"] = 500] = "internal_server_error"; + enum_status_code[enum_status_code["not_implemented"] = 501] = "not_implemented"; + enum_status_code[enum_status_code["bad_gateway"] = 502] = "bad_gateway"; + enum_status_code[enum_status_code["service_unavailable"] = 503] = "service_unavailable"; + enum_status_code[enum_status_code["gateway_timeout"] = 504] = "gateway_timeout"; + enum_status_code[enum_status_code["http_version_not_supported"] = 505] = "http_version_not_supported"; + enum_status_code[enum_status_code["variant_also_negotiates"] = 506] = "variant_also_negotiates"; + enum_status_code[enum_status_code["insufficient_storage"] = 507] = "insufficient_storage"; + enum_status_code[enum_status_code["loop_detected"] = 508] = "loop_detected"; + enum_status_code[enum_status_code["not_extended"] = 510] = "not_extended"; + enum_status_code[enum_status_code["network_authentication"] = 511] = "network_authentication"; + })(enum_status_code = http.enum_status_code || (http.enum_status_code = {})); + })(http = lib_plankton.http || (lib_plankton.http = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:http«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:http« 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:http« 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:http«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var http; + (function (http) { + /** + * @author fenris + */ + function encode_method(method) { + switch (method) { + case http.enum_method.get: return "GET"; + case http.enum_method.post: return "POST"; + case http.enum_method.patch: return "PATCH"; + case http.enum_method.put: return "PUT"; + case http.enum_method.delete: return "DELETE"; + case http.enum_method.options: return "OPTIONS"; + case http.enum_method.head: return "HEAD"; + default: throw (new Error("impossible")); + } + } + http.encode_method = encode_method; + /** + * @author fenris + */ + function decode_method(method_raw) { + switch (method_raw) { + case "GET": return http.enum_method.get; + case "POST": return http.enum_method.post; + case "PATCH": return http.enum_method.patch; + case "PUT": return http.enum_method.put; + case "DELETE": return http.enum_method.delete; + case "OPTIONS": return http.enum_method.options; + case "HEAD": return http.enum_method.head; + default: throw (new Error("unhandled method: " + method_raw)); + } + } + http.decode_method = decode_method; + /** + */ + function encode_status_code(status_code) { + return status_code.toFixed(0); + } + /** + * @todo check for existance + */ + function decode_status_code(status_code_raw) { + return parseInt(status_code_raw); + } + /** + * @author fenris + */ + function get_status_text(statuscode) { + switch (statuscode) { + case 100: return "Continue"; + case 101: return "Switching Protocols"; + case 103: return "Early Hints"; + case 200: return "OK"; + case 201: return "Created"; + case 202: return "Accepted"; + case 203: return "Non-Authoritative Information"; + case 204: return "No Content"; + case 205: return "Reset Content"; + case 206: return "Partial Content"; + case 300: return "Multiple Choices"; + case 301: return "Moved Permanently"; + case 302: return "Found"; + case 303: return "See Other"; + case 304: return "Not Modified"; + case 307: return "Temporary Redirect"; + case 308: return "Permanent Redirect"; + case 400: return "Bad Request"; + case 401: return "Unauthorized"; + case 402: return "Payment Required"; + case 403: return "Forbidden"; + case 404: return "Not Found"; + case 405: return "Method Not Allowed"; + case 406: return "Not Acceptable"; + case 407: return "Proxy Authentication Required"; + case 408: return "Request Timeout"; + case 409: return "Conflict"; + case 410: return "Gone"; + case 411: return "Length Required"; + case 412: return "Precondition Failed"; + case 413: return "Payload Too Large"; + case 414: return "URI Too Long"; + case 415: return "Unsupported Media Type"; + case 416: return "Range Not Satisfiable"; + case 417: return "Expectation Failed"; + case 418: return "I'm a teapot"; + case 422: return "Unprocessable Entity"; + case 425: return "Too Early"; + case 426: return "Upgrade Required"; + case 428: return "Precondition Required"; + case 429: return "Too Many Requests"; + case 431: return "Request Header Fields Too Large"; + case 451: return "Unavailable For Legal Reasons"; + case 500: return "Internal Server Error"; + case 501: return "Not Implemented"; + case 502: return "Bad Gateway"; + case 503: return "Service Unavailable"; + case 504: return "Gateway Timeout"; + case 505: return "HTTP Version Not Supported"; + case 506: return "Variant Also Negotiates"; + case 507: return "Insufficient Storage"; + case 508: return "Loop Detected"; + case 510: return "Not Extended"; + case 511: return "Network Authentication"; + default: throw (new Error("unhandled statuscode: " + statuscode.toFixed(0))); + } + } + /** + * @author fenris + */ + function has_body(method) { + return [ + http.enum_method.post, + http.enum_method.put, + http.enum_method.patch + ].includes(method); + } + http.has_body = has_body; + /** + * @author fenris + */ + function encode_request(request) { + return lib_plankton.http_base.encode_request(encode_method, request); + } + http.encode_request = encode_request; + /** + * @author fenris + */ + function decode_request(request_raw) { + return lib_plankton.http_base.decode_request(decode_method, has_body, request_raw); + } + http.decode_request = decode_request; + /** + * @author fenris + */ + function encode_response(response) { + return lib_plankton.http_base.encode_response(encode_status_code, get_status_text, response); + } + http.encode_response = encode_response; + /** + * @author fenris + */ + function decode_response(response_raw) { + return lib_plankton.http_base.decode_response(decode_status_code, response_raw); + } + http.decode_response = decode_response; + /** + * executes an HTTP request + * + * @todo define type_signal + */ + async function call(request, { "timeout": option_timeout = 5.0, "follow_redirects": option_follow_redirects = false, "implementation": option_implementation = "fetch", } = {}) { + return lib_plankton.http_base.call(has_body, encode_method, decode_status_code, request, { + "timeout": option_timeout, + "follow_redirects": option_follow_redirects, + "implementation": option_implementation, + }); + } + http.call = call; + })(http = lib_plankton.http || (lib_plankton.http = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:ical«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:ical« 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:ical« 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:ical«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var ical; + (function (ical) { + /** + */ + // type type_timestamp = string; + /** + */ + let enum_class; + (function (enum_class) { + enum_class["public"] = "public"; + enum_class["private"] = "private"; + enum_class["confidential"] = "confidential"; + })(enum_class = ical.enum_class || (ical.enum_class = {})); + ; + /** + */ + let enum_event_status; + (function (enum_event_status) { + enum_event_status["tentative"] = "tentative"; + enum_event_status["confirmed"] = "confirmed"; + enum_event_status["cancelled"] = "cancelled"; + })(enum_event_status = ical.enum_event_status || (ical.enum_event_status = {})); + ; + /** + */ + let enum_transp; + (function (enum_transp) { + enum_transp["opaque"] = "opaque"; + enum_transp["transparent"] = "transparent"; + })(enum_transp = ical.enum_transp || (ical.enum_transp = {})); + ; + })(ical = lib_plankton.ical || (lib_plankton.ical = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:ical«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:ical« 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:ical« 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:ical«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var ical; + (function (ical) { + /** + */ + function date_decode(date_encoded) { + return { + "year": parseInt(date_encoded.slice(0, 4)), + "month": parseInt(date_encoded.slice(4, 6)), + "day": parseInt(date_encoded.slice(6, 8)), + }; + } + /** + */ + function time_decode(time_encoded) { + return { + "hour": parseInt(time_encoded.slice(0, 2)), + "minute": parseInt(time_encoded.slice(2, 4)), + "second": parseInt(time_encoded.slice(4, 6)), + "utc": ((time_encoded.length >= 7) && (time_encoded[6] === "Z")) + }; + } + /** + */ + function datetime_decode(datetime_encoded) { + const parts = datetime_encoded.split("T", 2); + return { + "date": date_decode(parts[0]), + "time": ((parts.length >= 2) ? time_decode(parts[1]) : null), + }; + } + /** + */ + let enum_decode_state_label; + (function (enum_decode_state_label) { + enum_decode_state_label["expect_vcalendar_begin"] = "expect_vcalendar_begin"; + enum_decode_state_label["expect_vcalendar_property"] = "expect_vcalendar_property"; + enum_decode_state_label["expect_vevent_property"] = "expect_vevent_property"; + enum_decode_state_label["done"] = "done"; + })(enum_decode_state_label || (enum_decode_state_label = {})); + ; + /** + */ + function class_encode(class_) { + switch (class_) { + case ical.enum_class.private: { + return "PRIVATE"; + break; + } + case ical.enum_class.public: { + return "PUBLIC"; + break; + } + case ical.enum_class.confidential: { + return "CONFIDENTIAL"; + break; + } + } + } + /** + */ + function class_decode(class_encoded) { + return { + "PRIVATE": ical.enum_class.private, + "PUBLIC": ical.enum_class.public, + "CONFIDENTIAL": ical.enum_class.confidential, + }[class_encoded]; + } + /** + */ + function event_status_encode(event_status) { + switch (event_status) { + case ical.enum_event_status.tentative: { + return "TENTATIVE"; + break; + } + case ical.enum_event_status.confirmed: { + return "CONFIRMED"; + break; + } + case ical.enum_event_status.cancelled: { + return "CANCELLED"; + break; + } + } + } + /** + */ + function event_status_decode(event_status_encoded) { + return { + "TENTATIVE": ical.enum_event_status.tentative, + "CONFIRMED": ical.enum_event_status.confirmed, + "CANCELLED": ical.enum_event_status.cancelled, + }[event_status_encoded]; + } + /** + */ + function transp_encode(transp) { + switch (transp) { + case ical.enum_transp.opaque: { + return "OPAQUE"; + break; + } + case ical.enum_transp.transparent: { + return "TRANSPARENT"; + break; + } + } + } + /** + */ + function transp_decode(transp_encoded) { + return { + "OPAQUE": ical.enum_transp.opaque, + "TRANSPARENT": ical.enum_transp.transparent, + }[transp_encoded]; + } + /** + */ + function datetime_to_unixtimestamp(datetime) { + if ((datetime.time !== null) && (!datetime.time.utc)) { + throw (new Error("can not convert not utc time values")); + } + else { + return lib_plankton.pit.from_datetime({ + "timezone_shift": 0, + "date": { + "year": datetime.date.year, + "month": datetime.date.month, + "day": datetime.date.day, + }, + "time": { + "hour": ((datetime.time === null) ? 0 : datetime.time.hour), + "minute": ((datetime.time === null) ? 0 : datetime.time.minute), + "second": ((datetime.time === null) ? 0 : datetime.time.second), + } + }); + } + } + ical.datetime_to_unixtimestamp = datetime_to_unixtimestamp; + /** + * @see https://www.rfc-editor.org/rfc/rfc5545 + * @see https://icalendar.org/iCalendar-RFC-5545/ + * @todo implement edge cases + */ + function ics_decode_multi(ics_raw, { ignore_unhandled_instruction_keys = false, from_fucked_up_wordpress = false, } = {}) { + // preprocessing + let ics; + if (from_fucked_up_wordpress) { + ics = (ics_raw + .replace(new RegExp("\r", "g"), "") + .replace(new RegExp("END:VCALENDAR", "g"), "") + .replace(new RegExp("\n", "g"), "\r\n") + .replace(new RegExp("END:VEVENT", "g"), "END:VEVENT\r\nEND:VCALENDAR")); + lib_plankton.log.debug("plankton.ical.ics_decode.preprocessing.wordpress_fuckup", { + "result": ics, + }); + } + else { + ics = ics_raw; + } + const lines = ics.split("\r\n"); + let content_lines = []; + let content_line_buffer = null; + lines.forEach(line => { + if (line.trim() === "") { + // do nothing + } + else { + const is_folding = ((line.length >= 2) + && + ((line[0] === " ") + || + (line[0] === "\t")) + /* + && + ! ( + (line[1] === " ") + || + (line[1] === "\t") + ) + */ + ); + if (is_folding) { + content_line_buffer += line.slice(1); + } + else { + if (content_line_buffer === null) { + // do nothing + } + else { + content_lines.push(content_line_buffer); + } + content_line_buffer = line; + } + } + }); + if (content_line_buffer === null) { + // do nothing + } + else { + content_lines.push(content_line_buffer); + } + const instructions = content_lines.map((content_line) => { + const parts = content_line.split(":"); + const parts_left = parts[0].split(";"); + return { + "command": parts_left[0], + "parameters": Object.fromEntries(parts_left.slice(1).map(x => x.split("=", 2))), + "value": (parts.slice(1).join(":") + .split(";") + .map(x => x.replace(new RegExp("\\\\,", "g"), ","))), + }; + }); + lib_plankton.log.debug("plankton.ical.ics_decode_multi.instructions", { + "instructions": instructions, + }); + // core + let state = { + "label": enum_decode_state_label.expect_vcalendar_begin, + "vcalendar_list": [], + "vcalendar": null, + "vevent": null, + }; + instructions.forEach((instruction) => { + lib_plankton.log.debug("plankton.ical.ics_decode_multi.step", { + "state": state, + "current_instruction": instruction, + }); + switch (state.label) { + default: { + throw (new Error("unhandled state label: " + state.label)); + break; + } + case enum_decode_state_label.expect_vcalendar_begin: { + switch (instruction.command) { + default: { + lib_plankton.log.error("plankton.ical.ics_decode.error.vcalendar.unexpected_instruction_key", { + "state": state, + "instruction": instruction, + }); + throw (new Error("unexpected instruction key: " + instruction.command)); + break; + } + case "BEGIN": { + switch (instruction.value[0]) { + default: { + lib_plankton.log.error("plankton.ical.ics_decode.error.vcalendar.unexpected_instruction_value", { + "state": state, + "instruction": instruction, + }); + throw (new Error("unexpected instruction value: " + instruction.value[0])); + break; + } + case "VCALENDAR": { + state = { + "label": enum_decode_state_label.expect_vcalendar_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": { + "version": "", + "prodid": "", + "vevents": [], + }, + "vevent": null, + }; + break; + } + } + break; + } + } + break; + } + case enum_decode_state_label.expect_vcalendar_property: { + switch (instruction.command) { + case "VERSION": { + state = { + "label": enum_decode_state_label.expect_vcalendar_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": Object.assign(state.vcalendar, Object.fromEntries([["version", instruction.value[0]]])), + "vevent": state.vevent, + }; + break; + } + case "PRODID": { + state = { + "label": enum_decode_state_label.expect_vcalendar_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": Object.assign(state.vcalendar, Object.fromEntries([["prodid", instruction.value[0]]])), + "vevent": state.vevent, + }; + break; + } + case "METHOD": { + state = { + "label": enum_decode_state_label.expect_vcalendar_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": Object.assign(state.vcalendar, Object.fromEntries([["method", instruction.value[0]]])), + "vevent": state.vevent, + }; + break; + } + case "CALSCALE": { + state = { + "label": enum_decode_state_label.expect_vcalendar_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": Object.assign(state.vcalendar, Object.fromEntries([["calscale", instruction.value[0]]])), + "vevent": state.vevent, + }; + break; + } + case "BEGIN": { + const object = instruction.value[0]; + switch (object) { + default: { + lib_plankton.log.error("plankton.ical.ics_decode.error.vcalendar.unhandled_object", { + "state": state, + "instruction": instruction, + "object": object, + }); + throw (new Error("unhandled object: " + object)); + break; + } + case "VCALENDAR": { + lib_plankton.log.error("plankton.ical.ics_decode.error.vcalendar.unexpected_object", { + "state": state, + "instruction": instruction, + "object": object, + }); + throw (new Error("unexpected object: " + object)); + break; + } + case "VEVENT": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": { + "uid": "", + "dtstamp": { + "date": { "year": 2000, "month": 0, "day": 0 }, + "time": { "hour": 0, "minute": 0, "second": 0, "utc": true }, + }, + }, + }; + break; + } + } + break; + } + case "END": { + const object = instruction.value[0]; + switch (object) { + default: { + lib_plankton.log.error("plankton.ical.ics_decode.error.vcalendar.unhandled_object", { + "state": state, + "instruction": instruction, + "object": object, + }); + throw (new Error("unhandled object: " + object)); + break; + } + case "VCALENDAR": { + state = { + "label": enum_decode_state_label.expect_vcalendar_begin, + "vcalendar_list": state.vcalendar_list.concat([state.vcalendar]), + "vcalendar": null, + "vevent": state.vevent, + }; + break; + } + } + break; + } + default: { + if (instruction.command.startsWith("X-")) { + const key = instruction.command.slice(2).toLowerCase(); + const value = instruction.value.join(";"); + state = { + "label": enum_decode_state_label.expect_vcalendar_property, + "vcalendar_list": state.vcalendar_list, + /** + * @todo not sure; state.vcalendar might be null + */ + "vcalendar": Object.assign(state.vcalendar, { + "x_props": Object.assign((state.vcalendar.x_props ?? {}), Object.fromEntries([[key, value]])) + }), + "vevent": state.vevent, + }; + } + else { + lib_plankton.log.warning("plankton.ical.ics_decode.error.vcalendar.unhandled_instruction_key", { + "state": state, + "instruction": instruction, + }); + if (ignore_unhandled_instruction_keys) { + // do nothing + } + else { + throw (new Error("unhandled instruction key: " + instruction.command)); + } + } + break; + } + } + break; + } + case enum_decode_state_label.expect_vevent_property: { + switch (instruction.command) { + case "UID": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, Object.fromEntries([["uid", instruction.value[0]]])), + }; + break; + } + case "DTSTART": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, Object.fromEntries([ + [ + "dtstart", + Object.assign({ + "value": datetime_decode(instruction.value[0]), + }, (("tzid" in instruction.parameters) + ? + { + "tzid": instruction.parameters["tzid"], + } + : + {})) + ] + ])), + }; + break; + } + case "DTEND": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, Object.fromEntries([ + [ + "dtend", + Object.assign({ + "value": datetime_decode(instruction.value[0]), + }, (("tzid" in instruction.parameters) + ? + { + "tzid": instruction.parameters["tzid"], + } + : + {})) + ] + ])), + }; + break; + } + case "DTSTAMP": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, Object.fromEntries([ + [ + "dtstamp", + datetime_decode(instruction.value[0]) + ] + ])), + }; + break; + } + case "SEQUENCE": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, Object.fromEntries([["sequence", parseInt(instruction.value[0])]])), + }; + break; + } + case "TRANSP": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, Object.fromEntries([["transp", transp_decode(instruction.value[0])]])), + }; + break; + } + case "SUMMARY": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, Object.fromEntries([["summary", instruction.value[0]]])), + }; + break; + } + case "CLASS": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, Object.fromEntries([["class", class_decode(instruction.value[0])]])), + }; + break; + } + case "STATUS": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, Object.fromEntries([["status", event_status_decode(instruction.value[0])]])), + }; + break; + } + case "DESCRIPTION": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, Object.fromEntries([["description", instruction.value[0]]])), + }; + break; + } + case "CATEGORIES": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, Object.fromEntries([["categories", instruction.value[0].split(",")]])), + }; + break; + } + case "CREATED": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, Object.fromEntries([ + [ + "created", + { + "value": datetime_decode(instruction.value[0]), + } + ] + ])), + }; + break; + } + case "LOCATION": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, Object.fromEntries([["location", instruction.value[0]]])), + }; + break; + } + case "URL": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, Object.fromEntries([["url", instruction.value[0]]])), + }; + break; + } + case "LAST-MODIFIED": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, Object.fromEntries([ + [ + "last_modified", + { + "value": datetime_decode(instruction.value[0]), + } + ] + ])), + }; + break; + } + case "ATTENDEE": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, Object.fromEntries([["attendee", instruction.value[0]]])), + }; + break; + } + case "ORGANIZER": { + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, Object.fromEntries([ + [ + "organizer", + { + /** + * @todo parameters + */ + "value": instruction.value[0], + } + ] + ])), + }; + break; + } + case "BEGIN": { + const object = instruction.value[0]; + switch (object) { + default: { + lib_plankton.log.error("plankton.ical.ics_decode.error.vevent.unhandled_object", { + "state": state, + "instruction": instruction, + "object": object, + }); + throw (new Error("unhandled object: " + object)); + break; + } + case "VCALENDAR": { + lib_plankton.log.error("plankton.ical.ics_decode.error.vevent.unexpected_object", { + "state": state, + "instruction": instruction, + "object": object, + }); + throw (new Error("unexpected object: " + object)); + break; + } + case "VEVENT": { + lib_plankton.log.error("plankton.ical.ics_decode.error.vevent.unexpected_object", { + "state": state, + "instruction": instruction, + "object": object, + }); + throw (new Error("unexpected object: " + object)); + break; + } + } + break; + } + case "END": { + const object = instruction.value[0]; + switch (object) { + default: { + lib_plankton.log.error("plankton.ical.ics_decode.error.vevent.unhandled_value", { + "state": state, + "instruction": instruction, + "value": object, + }); + throw (new Error("unhandled value: " + object)); + break; + } + case "VEVENT": { + state = { + "label": enum_decode_state_label.expect_vcalendar_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": Object.assign(state.vcalendar, { + "vevents": state.vcalendar.vevents.concat([state.vevent]), + }), + "vevent": null, + }; + break; + } + } + break; + } + default: { + if (instruction.command.startsWith("X-")) { + const key = instruction.command.slice(2).toLowerCase(); + const value = instruction.value.join(";"); + state = { + "label": enum_decode_state_label.expect_vevent_property, + "vcalendar_list": state.vcalendar_list, + "vcalendar": state.vcalendar, + "vevent": Object.assign(state.vevent, { + "x_props": Object.assign((state.vevent.x_props ?? {}), Object.fromEntries([[key, value]])) + }), + }; + } + else { + lib_plankton.log.warning("plankton.ical.ics_decode.error.vevent.unhandled_instruction_key", { + "state": state, + "instruction": instruction, + }); + if (ignore_unhandled_instruction_keys) { + // do nothing + } + else { + throw (new Error("unhandled instruction key: " + instruction.command)); + } + } + break; + } + } + break; + } + case enum_decode_state_label.done: { + lib_plankton.log.error("plankton.ical.ics_decode.error.end_expected", { + "state": state, + "instruction": instruction, + }); + throw (new Error("end expected")); + break; + } + } + }); + return state.vcalendar_list; + } + ical.ics_decode_multi = ics_decode_multi; + /** + * @see https://www.rfc-editor.org/rfc/rfc5545 + * @see https://icalendar.org/iCalendar-RFC-5545/ + * @todo implement edge cases + */ + function ics_decode(ics, { ignore_unhandled_instruction_keys = false, from_fucked_up_wordpress = false, } = {}) { + const vcalendar_list = ics_decode_multi(ics, { + "ignore_unhandled_instruction_keys": ignore_unhandled_instruction_keys, + "from_fucked_up_wordpress": from_fucked_up_wordpress, + }); + if (vcalendar_list.length < 1) { + throw (new Error("no calendar data found")); + } + else { + if (vcalendar_list.length > 1) { + throw (new Error("ambiguous calendar data found")); + } + else { + return vcalendar_list[0]; + } + } + } + ical.ics_decode = ics_decode; + /** + * @see https://www.rfc-editor.org/rfc/rfc5545 + * @see https://icalendar.org/iCalendar-RFC-5545/ + */ + function date_encode(date) { + return lib_plankton.string.coin("{{year}}{{month}}{{day}}", { + "year": date.year.toFixed(0).padStart(4, "0"), + "month": date.month.toFixed(0).padStart(2, "0"), + "day": date.day.toFixed(0).padStart(2, "0"), + }); + } + /** + */ + function time_encode(time) { + return lib_plankton.string.coin("{{hour}}{{minute}}{{second}}{{utc}}", { + "hour": time.hour.toFixed(0).padStart(2, "0"), + "minute": time.minute.toFixed(0).padStart(2, "0"), + "second": time.second.toFixed(0).padStart(2, "0"), + "utc": (time.utc ? "Z" : ""), + }); + } + /** + */ + function datetime_encode(datetime) { + return lib_plankton.string.coin("{{date}}T{{time}}", { + "date": date_encode(datetime.date), + "time": time_encode(datetime.time), + }); + } + /** + * @todo method + * @todo add missing fields + */ + function ics_encode(vcalendar) { + let content_lines = []; + content_lines.push("BEGIN:VCALENDAR"); + content_lines.push(lib_plankton.string.coin("VERSION:{{version}}", { "version": vcalendar.version })); + content_lines.push(lib_plankton.string.coin("PRODID:{{prodid}}", { "prodid": vcalendar.prodid })); + content_lines.push(lib_plankton.string.coin("METHOD:{{method}}", { "method": vcalendar.method })); + vcalendar.vevents.forEach((vevent) => { + content_lines.push("BEGIN:VEVENT"); + { + // uid + content_lines.push(lib_plankton.string.coin("UID:{{uid}}", { + "uid": vevent.uid, + })); + // dtstart + content_lines.push(lib_plankton.string.coin( + // "DTSTART;TZID={{tzid}}:{{value}}", + "DTSTART:{{value}}", { + "tzid": vevent.dtstart.tzid, + "value": datetime_encode(vevent.dtstart.value), + })); + // dtend + if (vevent.dtend !== undefined) { + content_lines.push(lib_plankton.string.coin( + // "DTEND;TZID={{tzid}}:{{value}}", + "DTEND:{{value}}", { + "tzid": vevent.dtend.tzid, + "value": datetime_encode(vevent.dtend.value), + })); + } + // dtstamp + content_lines.push(lib_plankton.string.coin("DTSTAMP:{{value}}", { + "value": datetime_encode(vevent.dtstamp), + })); + // class + if (vevent.class !== undefined) { + content_lines.push(lib_plankton.string.coin("CLASS:{{class}}", { + "class": vevent.class, + })); + } + // summary + content_lines.push(lib_plankton.string.coin("SUMMARY:{{summary}}", { + "summary": vevent.summary, + })); + // description + if (vevent.description !== undefined) { + content_lines.push(lib_plankton.string.coin("DESCRIPTION:{{description}}", { + "description": vevent.description, + })); + } + // location + if (vevent.location !== undefined) { + content_lines.push(lib_plankton.string.coin("LOCATION:{{location}}", { + "location": vevent.location, + })); + } + // geo + if (vevent.geo !== undefined) { + content_lines.push(lib_plankton.string.coin("GEO:{{geo_latitude}};{{geo_longitude}}", { + "geo_latitude": vevent.geo.latitude.toFixed(4), + "geo_longitude": vevent.geo.longitude.toFixed(4), + })); + } + // url + if (vevent.url !== undefined) { + content_lines.push(lib_plankton.string.coin("URL:{{url}}", { + "url": vevent.url, + })); + } + } + content_lines.push("END:VEVENT"); + }); + content_lines.push("END:VCALENDAR"); + let lines = []; + content_lines.forEach((content_line) => { + const slices = lib_plankton.string.slice(content_line, 75 - 1); + lines.push(slices[0]); + slices.slice(1).forEach((slice) => { lines.push(" " + slice); }); + }); + return lines.join("\r\n"); + } + ical.ics_encode = ics_encode; + })(ical = lib_plankton.ical || (lib_plankton.ical = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2024 '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-2024 '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-2024 '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-2024 '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-2024 '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-2024 '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-2024 '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-2024 '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-2024 '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-2024 '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-2024 '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(source, options = {}) { + options = Object.assign({ + "formatted": false, + }, options); + return JSON.stringify(source, undefined, (options.formatted ? "\t" : undefined)); + } + json.encode = encode; + /** + * @author fenris + */ + function decode(target) { + return JSON.parse(target); + } + json.decode = decode; + /** + * @author fenris + */ + function implementation_code() { + return { + "encode": x => encode(x), + "decode": decode, + }; + } + json.implementation_code = implementation_code; + })(json = lib_plankton.json || (lib_plankton.json = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:json«. + +Copyright 2016-2024 '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:telegram«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:telegram« 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:telegram« 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:telegram«. If not, see . + */ +/* +This file is part of »bacterio-plankton:telegram«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:telegram« 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:telegram« 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:telegram«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var telegram; + (function (telegram) { + /** + */ + const conf = { + "host": "api.telegram.org", + }; + /** + */ + async function bot_call_generic(token, action, input) { + const http_request = { + "version": "HTTP/2", + "scheme": "https", + "host": conf.host, + "path": lib_plankton.string.coin("/bot{{token}}/{{action}}", { + "token": token, + "action": action, + }), + "query": "", + "method": lib_plankton.http.enum_method.post, + "headers": { + "content-type": "application/json", + }, + "body": Buffer.from(lib_plankton.json.encode(input)), + }; + const http_response = await lib_plankton.http.call(http_request); + const output_wrapped = lib_plankton.json.decode(http_response.body.toString()); + if (!output_wrapped.ok) { + return Promise.reject(new Error()); + } + else { + return Promise.resolve(output_wrapped.result); + } + } + /** + * @see https://core.telegram.org/bots/api#getupdates + */ + async function bot_call_get_updates(token) { + const output = await bot_call_generic(token, "getUpdates", {}); + return output; + } + telegram.bot_call_get_updates = bot_call_get_updates; + /** + * @see https://core.telegram.org/bots/api#sendmessage + */ + async function bot_call_send_message(token, chat_id, text) { + const output = await bot_call_generic(token, "sendMessage", { + "chat_id": chat_id, + "text": text, + }); + } + telegram.bot_call_send_message = bot_call_send_message; + })(telegram = lib_plankton.telegram || (lib_plankton.telegram = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:file«. + +Copyright 2016-2024 '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 exists(path) { + var nm_fs = require("fs"); + return (new Promise(function (resolve, reject) { + nm_fs.stat(path, function (error, stats) { + if (error) { + resolve(false); + } + else { + resolve(true); + } + }); + })); + } + file.exists = exists; + /** + * @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; + /** + */ + function delete_(path) { + var nm_fs = require("fs"); + return (new Promise(function (resolve, reject) { + nm_fs.unlink(path, function () { + resolve(undefined); + }); + })); + } + file.delete_ = delete_; + })(file = lib_plankton.file || (lib_plankton.file = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:object«. + +Copyright 2016-2024 '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 + * @deprecated use the "??" operator instead + */ + function fetch(object, fieldname, options) { + if (options === void 0) { options = {}; } + options = Object.assign({ + "fallback": null, + "escalation": 1 + }, options); + if ((fieldname in object) + && + (object[fieldname] !== undefined)) { + return object[fieldname]; + } + else { + if (!options.escalate) { + return options.fallback; + } + else { + throw (new Error("field '" + fieldname + "' not in structure")); + } + } + } + object_1.fetch = fetch; + /** + */ + function map(object_from, transformator) { + return (Object.fromEntries(Object.entries(object_from) + .map(function (_a) { + var key = _a[0], value = _a[1]; + return ([key, transformator(value, key)]); + }))); + } + object_1.map = map; + /** + * gibt ein Objekt mit bestimmten Einträgen des Eingabe-Objekts zurück + */ + function filter(object_from, predicate) { + return (Object.fromEntries(Object.entries(object_from) + .filter(function (_a) { + var key = _a[0], value = _a[1]; + return predicate(value, key); + }))); + } + object_1.filter = filter; + /** + * wandelt ein Array mit Einträgen der Form {key,value} in ein entsprechendes Objekt um + * + * @deprecated use Object.fromEntries instead! + */ + function from_array(array) { + return (Object.fromEntries(array + .map(function (_a) { + var key = _a["key"], value = _a["value"]; + return ([key, value]); + }))); + } + object_1.from_array = from_array; + /** + * wandelt ein Objekt in ein entsprechendes Array mit Einträgen der Form {key,value} um + * + * @deprecated use Object.entries insetad! + */ + function to_array(object) { + return (Object.entries(object) + .map(function (_a) { + var key = _a[0], value = _a[1]; + return ({ "key": key, "value": value }); + })); + } + object_1.to_array = to_array; + /** + * gibt eine Liste von Schlüsseln eines Objekts zurück + * + * @deprecated use Object.keys instead! + */ + function keys(object) { + return Object.keys(object); + } + object_1.keys = keys; + /** + * gibt eine Liste von Werten eines Objekts zurück + * + * @deprecated use Object.values instead! + */ + function values(object) { + return Object.values(object); + } + object_1.values = values; + /** + * liest ein Baum-artiges Objekt an einer bestimmten Stelle aus + */ + function path_read(object, path, options) { + if (options === void 0) { options = {}; } + options = Object.assign({ + "fallback": null, + "escalate": false + }, options); + 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, { + "fallback": null, + "escalate": false + }); + return (position_1 != null); + }))); + if (reachable) { + return lib_plankton.object.fetch(position_1, steps[steps.length - 1], { + "fallback": options.fallback, + "escalate": options.escalate + }); + } + else { + return lib_plankton.object.fetch({}, "_dummy_", { + "fallback": options.fallback, + "escalate": options.escalate + }); + } + } + } + object_1.path_read = path_read; + /** + * schreibt einen Wert an eine bestimmte Stelle in einem Baum-artigen Objekt + */ + 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, { + "fallback": null, + "escalate": false + }); + 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 { + throw (new Error("path '" + path + "' does not exist and may not be constructed")); + } + } + } + object_1.path_write = path_write; + /** + * prüft ob ein Objekt einem bestimmten Muster entspricht + * + * @deprecated not very useful + */ + function matches(object, pattern, options) { + if (options === void 0) { options = {}; } + options = Object.assign({ + "collate": instance_collate + }, options); + return (Object.entries(pattern) + .every(function (_a) { + var key = _a[0], value = _a[1]; + return options.collate(value, object[key]); + })); + } + object_1.matches = matches; + /** + * erzeugt eine Projektion eines Baum-artigen Objekts in ein Listen-artiges Objekt + */ + function flatten(value, options) { + if (options === void 0) { options = {}; } + options = Object.assign({ + "separator": ".", + "key_for_array_element": (function (index) { return ("element_" + index.toFixed(0)); }) + }, options); + 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_ = flatten(value, { + "separator": options.separator, + "key_for_array_element": options.key_for_array_element + }); + Object.entries(result_).forEach(function (_a) { + var key_ = _a[0], value_ = _a[1]; + result[(key + options.separator + key_)] = value_; + }); + } + } + }; + if ((value === null) + || + (value === undefined)) { + return null; + } + else { + var result_1 = {}; + if (typeof (value) != "object") { + result_1["value"] = value; + } + else { + if (value instanceof Array) { + value.forEach(function (element, index) { + integrate(result_1, options.key_for_array_element(index), element); + }); + } + else { + Object.entries(value).forEach(function (_a) { + var key = _a[0], value = _a[1]; + integrate(result_1, key, value); + }); + } + } + return result_1; + } + } + object_1.flatten = flatten; + /** + * @deprecated use Object.assign instead! + */ + function clash(x, y, options) { + if (options === void 0) { options = {}; } + options = Object.assign({ + "overwrite": true, + "hooks": { + "existing": function (key, value_old, value_new) { + lib_plankton.log.warning("object_clash_field_already_defined", { + "key": key + }); + } + } + }, options); + var z = {}; + Object.keys(x).forEach(function (key) { + z[key] = x[key]; + }); + Object.keys(y).forEach(function (key) { + if (key in z) { + if (options.hooks.existing != null) { + options.hooks.existing(key, z[key], y[key]); + } + if (options.overwrite) { + z[key] = y[key]; + } + } + else { + z[key] = y[key]; + } + }); + return z; + } + object_1.clash = clash; + /** + * @deprecated use Object.assign instead! + */ + function patch(core, mantle, options) { + if (options === void 0) { options = {}; } + options = Object.assign({ + "deep": true, + "path": null + }, options); + if (mantle == null) { + lib_plankton.log.warning("object_patch_mantle_is_null", { + "core": core + }); + } + else { + Object.keys(mantle).forEach(function (key) { + var path_ = ((options.path == null) + ? + key + : + (options.path + "." + key)); + var value_mantle = mantle[key]; + if (!(key in core)) { + if ((typeof (value_mantle) == "object") + && + (value_mantle != null) + && + options.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": options.deep, + "path": 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) + && + options.deep) { + patch(core[key], value_mantle, { + "deep": options.deep, + "path": path_ + }); + } + else { + core[key] = value_mantle; + } + } + else { + if ((value_core != null) + && + (value_mantle != null)) { + lib_plankton.log.warning("object_path_different_shapes", { + "path": path_, + "core_type": typeof (value_core), + "mantle_type": typeof (value_mantle) + }); + } + core[key] = value_mantle; + // throw (new Error(message)); + } + } + }); + } + } + object_1.patch = patch; + /** + * @deprecated use Object.assign instead! + */ + function patched(core, mantle, options) { + if (options === void 0) { options = {}; } + options = Object.assign({ + "deep": true + }, options); + var result = {}; + patch(result, core, { "deep": options.deep }); + patch(result, mantle, { "deep": options.deep }); + return result; + } + object_1.patched = patched; + /** + * @deprecated use Object.assign instead! + */ + function attached(object, key, value) { + var mantle = {}; + mantle[key] = value; + return patched(object, mantle, { "deep": 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:pair«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:pair« 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:pair« 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:pair«. If not, see . + */ +/* +This file is part of »bacterio-plankton:pair«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:pair« 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:pair« 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:pair«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var pair; + (function (pair_1) { + /** + */ + function swap(pair) { + return { + "first": pair.second, + "second": pair.first + }; + } + pair_1.swap = swap; + /** + */ + function show(pair, options) { + if (options === void 0) { options = {}; } + options = Object.assign({ + "show_first": instance_show, + "show_second": instance_show + }, options); + return ("(" + + + options.show_first(pair.first) + + + "," + + + options.show_second(pair.second) + + + ")"); + } + pair_1.show = show; + })(pair = lib_plankton.pair || (lib_plankton.pair = {})); +})(lib_plankton || (lib_plankton = {})); +"use strict"; +/* +This file is part of »bacterio-plankton:list«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:list« 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:list« 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:list«. If not, see . + */ +/* +This file is part of »bacterio-plankton:list«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:list« 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:list« 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:list«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var list; + (function (list_1) { + /** + * returns a certain list of integer numbers + */ + function range(from, to, options) { + if (options === void 0) { options = {}; } + options = Object.assign({ + "step": 1 + }, options); + var list = []; + for (var value = from; value <= to; value += options.step) { + list.push(value); + } + return list; + } + list_1.range = range; + /** + * returns a certain list of consecutiv integer numbers, beginning with 0 + */ + function sequence(length) { + return range(0, length - 1); + } + list_1.sequence = sequence; + /** + */ + function from_iterator(iterator) { + var list = []; + // @ts-ignore + for (var _i = 0, iterator_1 = iterator; _i < iterator_1.length; _i++) { + var element = iterator_1[_i]; + list.push(element); + } + return list; + } + list_1.from_iterator = from_iterator; + /** + */ + function is_empty(list) { + return (list.length <= 0); + } + list_1.is_empty = is_empty; + /** + * combines two lists into one + * + * @param {boolean} [options.cut] whether the result list will be as long as the shortest input list or an exception is thrown if they have different lengths; default: true + */ + function zip(list_first, list_second, options) { + if (options === void 0) { options = {}; } + options = Object.assign({ + "cut": true + }, options); + var empty_first = is_empty(list_first); + var empty_second = is_empty(list_second); + if (empty_first || empty_second) { + if (options.cut || (empty_first && empty_second)) { + return []; + } + else { + throw (new Error("lists have different lengths")); + } + } + else { + return ([{ "first": list_first[0], "second": list_second[0] }] + .concat(zip(list_first.slice(1), list_second.slice(1), { + "cut": options.cut + }))); + } + } + list_1.zip = zip; + /** + * checks whether two lists are equal + * + * @todo define common function "equals" and default predicate to + */ + function equals(list1, list2, options) { + if (options === void 0) { options = {}; } + options = Object.assign({ + "collate_element": instance_collate + }, options); + if (list1.length == list2.length) { + return (zip(list1, list2, { "cut": true }) + .every(function (pair) { return options.collate_element(pair.first, pair.second); })); + } + else { + return false; + } + } + list_1.equals = equals; + /** + * creates a list with the elements from the input list, which fulfil a certain predicate (~ filter) + */ + function keep(list, predicate) { + return (list + .filter(function (element, index) { return predicate(element); })); + } + list_1.keep = keep; + /** + * creates a list with the elements from the input list, which do not fulfil a certain predicate (~ dual filter) + */ + function drop(list, predicate) { + return (list + .filter(function (element, index) { return (!predicate(element)); })); + } + list_1.drop = drop; + /** + */ + function filter_inplace(list, predicate) { + var index = 0; + while (index < list.length) { + var element = list[index]; + if (predicate(element)) { + index += 1; + } + else { + list.splice(index, 1); + } + } + } + list_1.filter_inplace = filter_inplace; + /** + * returns a list with no duplicates (like unix' "unique") + */ + function cleaned(list, options) { + if (options === void 0) { options = {}; } + options = Object.assign({ + "collate_element": instance_collate + }, options); + var list_ = []; + list.forEach(function (element) { + if (!list_.some(function (element_) { return options.collate_element(element, element_); })) { + list_.push(element); + } + else { + // do nothing + } + }); + return list_; + } + list_1.cleaned = cleaned; + /** + * creates a binary partition of the list according to a given predicate + */ + function separate(list, predicate) { + return (list + .reduce(function (seperation, element) { + return (predicate(element) + ? { "yes": seperation.yes.concat([element]), "no": seperation["no"] } + : { "yes": seperation.yes, "no": seperation["no"].concat([element]) }); + }, { "yes": [], "no": [] })); + } + list_1.separate = separate; + ; + /** + */ + function clone(list) { + return keep(list, function (x) { return true; }); + } + list_1.clone = clone; + /** + */ + function reversed(list) { + var list_ = clone(list); + list_.reverse(); + return list_; + } + list_1.reversed = reversed; + /** + * @todo use Array.toSorted? + */ + function sorted(list, options) { + options = Object.assign({ + "compare_element": instance_compare + }, options); + var list_ = clone(list); + list_.sort(function (x, y) { return (options.compare_element(x, y) ? -1 : +1); }); + return list_; + } + list_1.sorted = sorted; + /** + * die Liste in gleich große Blöcke zerlegen + */ + function chop(list, chunk_size) { + var chunks = []; + var index = 0; + while (index < list.length) { + var chunk = list.slice(index, Math.min(list.length, index + chunk_size)); + index += chunk_size; + chunks.push(chunk); + } + return chunks; + } + list_1.chop = chop; + /** + */ + function group(list, collate_element) { + var result = []; + list.forEach(function (element) { + var target = result.find( + // @ts-ignore + function (group) { return collate_element(group[0], element); }); + if (target === undefined) { + target = []; + result.push(target); + } + target.push(element); + }); + return result; + } + list_1.group = group; + /** + */ + function has(list, predicate) { + return (list.find(predicate) !== undefined); + } + list_1.has = has; + /** + * @deprecate use Array.includes or Array.some + */ + function contains(list, element, options) { + options = Object.assign({ + "collate": instance_collate + }, options); + return has(list, function (element_) { return options.collate_element(element_, element); }); + } + list_1.contains = contains; + /** + * retrieves the element and its index of the list, which has the maximum value + */ + function max(list, target_function, options) { + options = Object.assign({ + "compare_value": instance_compare + }, options); + if (is_empty(list)) { + throw (new Error("the max-arg of an empty list is not defined")); + } + else { + return (list + .reduce(function (result, element, index) { + var value = target_function(element); + if ((result == null) + || + (!options.compare_value(value, result.value))) { + return { "index": index, "element": element, "value": value }; + } + else { + return result; + } + }, null)); + } + } + list_1.max = max; + /** + * retrieves the element and its index of the list, which has the mininum value + */ + function min(list, target_function, options) { + options = Object.assign({ + "compare_value": instance_compare + }, options); + return max(list, target_function, { + "compare_value": function (x, y) { return options.compare_value(y, x); } + }); + } + list_1.min = min; + /** + * implements the idea of arithmetic distribution like in "(a+b)·(c+d) = (a·c)+(a·d)+(b·c)+(b·d)" + * example: distribute([[1,2],[3],[4,5,6]]) = [[1,3,4],[1,3,5],[1,3,6],[2,3,4],[2,3,5],[2,3,6]] + */ + function distribute(lists) { + if (is_empty(lists)) { + return [[]]; + } + else { + var subresult_1 = distribute(lists.slice(1)); + return (lists[0] + .map(function (element) { return subresult_1.map(function (list) { return [element].concat(list); }); }) + .reduce(function (x, y) { return x.concat(y); }, [])); + } + } + list_1.distribute = distribute; + /** + */ + function contrast(list_left, extract_key_left, list_right, extract_key_right) { + var gathering = {}; + list_left.forEach(function (source_left) { + var _a; + var key = extract_key_left(source_left); + gathering[key] = Object.assign(((_a = gathering[key]) !== null && _a !== void 0 ? _a : {}), { "left": source_left }); + }); + list_right.forEach(function (source_right) { + var _a; + var key = extract_key_right(source_right); + gathering[key] = Object.assign(((_a = gathering[key]) !== null && _a !== void 0 ? _a : {}), { "right": source_right }); + }); + var result = { + "both": [], + "only_left": [], + "only_right": [] + }; + Object.entries(gathering).forEach(function (_a) { + var key = _a[0], value = _a[1]; + if ("left" in value) { + if ("right" in value) { + result.both.push({ "key": key, "left": value.left, "right": value.right }); + } + else { + result.only_left.push({ "key": key, "left": value.left }); + } + } + else { + if ("right" in value) { + result.only_right.push({ "key": key, "right": value.right }); + } + else { + // impossible + // do nothing + } + } + }); + return result; + } + list_1.contrast = contrast; + })(list = lib_plankton.list || (lib_plankton.list = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:conf«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:conf« 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:conf« 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:conf«. If not, see . + */ +/* +This file is part of »bacterio-plankton:conf«. + +Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:conf« 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:conf« 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:conf«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var conf; + (function (conf) { + /** + */ + function adapt_primitive(schema, value) { + if (value === undefined) { + if (!("default" in schema)) { + return { + "reports": [ + { + "incident": "neither explicit value provided nor default value specified", + "details": {} + } + ], + "result": lib_plankton.pod.make_empty(), + }; + } + else { + return { + "reports": [], + "result": lib_plankton.pod.make_filled(schema.default), + }; + } + } + else { + if (value === null) { + if (("nullable" in schema) + && + (!schema.nullable)) { + return { + "reports": [ + { + "incident": "null not allowed", + "details": {} + } + ], + "result": lib_plankton.pod.make_empty(), + }; + } + else { + return { + "reports": [], + "result": lib_plankton.pod.make_filled(null), + }; + } + } + else { + if (("enum" in schema) + && + (!schema.enum.includes(value))) { + return { + "reports": [ + { + "incident": "provided value not in enumeration of valid values", + "details": { + "enumerated_values": schema.enum, + "provided_value": value, + } + } + ], + "result": lib_plankton.pod.make_empty(), + }; + } + else { + const type_map = { + "boolean": "boolean", + "integer": "number", + "number": "number", + "string": "string", + }; + // @ts-ignore + if (!(typeof (value) === type_map[schema.type])) { + return { + "reports": [ + { + // @ts-ignore + "incident": ("value should be " + type_map[schema.type]), + "details": { + "provided_value": value, + "type": typeof (value), + } + } + ], + "result": lib_plankton.pod.make_empty(), + }; + } + else { + return { + "reports": [], + "result": lib_plankton.pod.make_filled(value) + }; + } + } + } + } + } + /** + * @todo anyOf + * @todo allOf + * @todo oneOf + * @todo not + * @todo tests + */ + function adapt(schema, value_raw) { + let value = value_raw; + if (!("type" in schema)) { + if ("anyOf" in schema) { + if (value === undefined) { + if (!("default" in schema)) { + return { + "reports": [ + { + "incident": "neither explicit value provided nor default value specified", + "details": {} + } + ], + "result": lib_plankton.pod.make_empty(), + }; + } + else { + value = schema.default; + } + } + else { + // do nothing + } + const sub_adaptions = (schema.anyOf + .map((sub_schema) => adapt(sub_schema, value))); + const valid_sub_adaptions = (sub_adaptions + .filter((sub_adaption) => lib_plankton.pod.is_filled(sub_adaption.result))); + if (valid_sub_adaptions.length <= 0) { + return { + "reports": [ + { + "incident": "no valid adaptions", + "details": { + "sub_adaptions": sub_adaptions, + } + } + ], + "result": lib_plankton.pod.make_empty(), + }; + } + else { + if (valid_sub_adaptions.length > 1) { + return { + "reports": [ + { + "incident": "multiple valid apaptions", + "details": { + "valid_sub_adaptions": valid_sub_adaptions, + } + } + ], + "result": lib_plankton.pod.make_empty(), + }; + } + else { + return valid_sub_adaptions[0]; + } + } + } + else { + throw (new Error("not implemented")); + } + } + else { + switch (schema.type) { + case "boolean": + return adapt_primitive(schema, value); + break; + case "integer": + return adapt_primitive(schema, value); + break; + case "number": + return adapt_primitive(schema, value); + break; + case "string": { + return adapt_primitive(schema, value); + break; + } + case "array": { + if (value === undefined) { + if (!("default" in schema)) { + return { + "reports": [ + { + "incident": "neither explicit value provided nor default value specified", + "details": {} + } + ], + "result": lib_plankton.pod.make_empty(), + }; + } + else { + value = schema.default; + } + } + /*else*/ { + if (value === null) { + if (("nullable" in schema) + && + (!schema.nullable)) { + return { + "reports": [ + { + "incident": "null not allowed", + "details": {} + } + ], + "result": lib_plankton.pod.make_empty(), + }; + } + else { + return { + "reports": [], + "result": lib_plankton.pod.make_filled(null), + }; + } + } + else { + /*if ( + ("enum" in schema) + && + (! schema.enum.includes(value)) // TODO + ) { + return { + "reports": [ + { + "incident": "provided value not in enumeration of valid values", + "details": { + "enumerated_values": schema.enum, + "provided_value": value, + } + } + ], + "result": lib_plankton.pod.make_empty(), + }; + } + else*/ { + if ((!(typeof (value) === "object")) + && + (value.constructor.name !== "Array")) { + return { + "reports": [ + { + "incident": "value should be array", + "details": { + "provided_value": value, + } + } + ], + "result": lib_plankton.pod.make_empty(), + }; + } + else { + if (!("items" in schema)) { + // do nothing + return { + "reports": [], + "result": lib_plankton.pod.make_filled(value), + }; + } + else { + let reports = []; + for (let index = 0; index < value.length; index += 1) { + const adaption = adapt(schema.items, value[index]); + if (!lib_plankton.pod.is_filled(adaption.result)) { + reports = reports.concat(adaption.reports.map((report_entry) => ({ + "incident": report_entry.incident, + "details": Object.assign(report_entry.details, { + "path": (report_entry.details.path ?? []).concat([index]) + }), + }))); + } + else { + value[index] = lib_plankton.pod.cull(adaption.result); + } + } + return { + "reports": reports, + "result": ((reports.length > 0) + ? + lib_plankton.pod.make_empty() + : + lib_plankton.pod.make_filled(value)), + }; + } + } + } + } + } + break; + } + case "object": { + if (value === undefined) { + if (!("default" in schema)) { + return { + "reports": [ + { + "incident": "neither explicit value provided nor default value specified", + "details": {} + } + ], + "result": lib_plankton.pod.make_empty(), + }; + } + else { + value = schema.default; + } + } + /*else*/ { + if (value === null) { + if (("nullable" in schema) + && + (!schema.nullable)) { + return { + "reports": [ + { + "incident": "null not allowed", + "details": {} + } + ], + "result": lib_plankton.pod.make_empty(), + }; + } + else { + return { + "reports": [], + "result": lib_plankton.pod.make_filled(null), + }; + } + } + else { + /*if ( + ("enum" in schema) + && + (! schema.enum.includes(value)) // TODO + ) { + return { + "reports": [ + { + "incident": "provided value not in enumeration of valid values", + "details": { + "enumerated_values": schema.enum, + "provided_value": value, + } + } + ], + "result": lib_plankton.pod.make_empty(), + }; + } + else*/ { + if (!(typeof (value) === "object")) { + return { + "reports": [ + { + "incident": "value should be object", + "details": { + "provided_value": value, + } + } + ], + "result": lib_plankton.pod.make_empty(), + }; + } + else { + value = lib_plankton.object.copy(value); + const contrast = lib_plankton.list.contrast(Object.keys(schema.properties), x => x, Object.keys(value), x => x); + let reports = []; + // gratuitous fields + { + if (contrast.only_right.length <= 0) { + // do nothing + } + else { + const additional_properties = (schema.additionalProperties ?? false); + if (additional_properties === false) { + reports = reports.concat(contrast.only_right + .map((entry) => ({ + "incident": "gratuitous field", + "details": { + "path": [entry.right], + } + }))); + } + else { + contrast.only_right.forEach((entry) => { + const sub_adaption = adapt(additional_properties, value[entry.right]); + if (!lib_plankton.pod.is_filled(sub_adaption.result)) { + reports = reports.concat(sub_adaption.reports + .map((report_entry) => ({ + "incident": report_entry.incident, + "details": Object.assign(report_entry.details, { + "path": [entry.right].concat(report_entry.details.path ?? []), + }), + }))); + } + else { + value[entry.right] = lib_plankton.pod.cull(sub_adaption.result); + } + }); + } + } + } + // missing fields + { + contrast.only_left.forEach((entry) => { + if (("required" in schema) + && + schema.required.includes(entry.left)) { + reports.push({ + "incident": "missing field", + "details": { + "path": [entry.left], + } + }); + } + else { + const sub_adaption = adapt(schema.properties[entry.left], undefined); + if (!lib_plankton.pod.is_filled(sub_adaption.result)) { + reports = reports.concat(sub_adaption.reports + .map((report_entry) => ({ + "incident": report_entry.incident, + "details": Object.assign(report_entry.details, { + "path": [entry.left].concat(report_entry.details.path ?? []), + }), + }))); + } + else { + value[entry.left] = lib_plankton.pod.cull(sub_adaption.result); + } + } + }); + // regular fields + { + contrast.both.forEach((entry) => { + const sub_adaption = adapt(schema.properties[entry.left], value[entry.right]); + if (!lib_plankton.pod.is_filled(sub_adaption.result)) { + reports = reports.concat(sub_adaption.reports + .map((report_entry) => ({ + "incident": report_entry.incident, + "details": Object.assign(report_entry.details, { + "path": [entry.right].concat(report_entry.details.path ?? []), + }), + }))); + } + else { + value[entry.right] = lib_plankton.pod.cull(sub_adaption.result); + } + }); + } + return { + "reports": reports, + "result": ((reports.length > 0) + ? + lib_plankton.pod.make_empty() + : + lib_plankton.pod.make_filled(value)), + }; + } + } + } + } + } + break; + } + default: { + throw (new Error("unhandled schema type: " + schema.type)); + break; + } + } + } + } + /** + * @todo versioning + */ + function refine(schema, value_raw) { + const adaption = adapt(schema, value_raw); + if (!lib_plankton.pod.is_filled(adaption.result)) { + throw (new Error("conf could not be loaded:\n" + + + (adaption.reports + .map((report) => ("- " + report.incident + " | " + JSON.stringify(report.details, undefined, "\t"))) + .join("\n")))); + } + else { + return lib_plankton.pod.cull(adaption.result); + } + } + conf.refine = refine; + /** + */ + function load(schema, path) { + return (((path === null) + ? + Promise.resolve(undefined) + : + (lib_plankton.file.read(path) + .then((content) => Promise.resolve(lib_plankton.json.decode(content))))) + .then((data_raw) => Promise.resolve(refine(schema, data_raw)))); + } + conf.load = load; + })(conf = lib_plankton.conf || (lib_plankton.conf = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:args«. + +Copyright 2016-2024 '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-2024 '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-2024 '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/conf.ts b/source/conf.ts new file mode 100644 index 0000000..a62ef83 --- /dev/null +++ b/source/conf.ts @@ -0,0 +1,149 @@ +namespace _lixer_event_reminder.conf +{ + + /** + */ + export type type_conf = { + bot_token : string; + sources : Array< + ( + { + kind : "kalender_digital", + data : { + id : string; + filtration : { + category_blacklist : Array; + title_blacklist : Array; + }; + }; + } + ) + >; + targets : Array< + { + chat_id : int; + interval : Array; + } + >; + }; + + + /** + */ + export const schema : lib_plankton.conf.type_schema = { + "nullable": false, + "type": "object", + "properties": { + "version": { + "nullable": false, + "type": "string", + }, + "bot_token": { + "nullable": false, + "type": "string", + }, + "sources": { + "nullable": false, + "type": "array", + "items": { + "nullable": false, + "anyOf": [ + { + "type": "object", + "properties": { + "kind": { + "nullable": false, + "type": "string", + "enum": ["kalender_digital"] + }, + "data": { + "nullable": false, + "type": "object", + "properties": { + "id": { + "nullable": false, + "type": "string" + }, + "filtration": { + "nullable": false, + "type": "object", + "properties": { + "category_blacklist": { + "nullable": false, + "type": "array", + "items": { + "nullable": false, + "type": "string", + } + }, + "title_blacklist": { + "nullable": false, + "type": "array", + "items": { + "nullable": false, + "type": "string", + } + }, + }, + "additionalProperties": false, + "required": [ + "category_blacklist", + "title_blacklist", + ] + }, + }, + "additionalProperties": false, + "required": [ + "id", + "filtration", + ] + } + }, + "additionalProperties": false, + "required": [ + "kind", + "data", + ] + } + ] + } + }, + "targets": { + "nullable": false, + "type": "array", + "items": { + "nullable": false, + "type": "object", + "properties": { + "chat_id": { + "nullable": false, + "type": "integer", + }, + "interval": { + "nullable": false, + "type": "array", + "items": { + "nullable": false, + "type": "integer" + } + }, + }, + "additionalProperties": false, + "required": [ + "chat_id", + "interval", + ] + } + }, + }, + "additionalProperties": false, + "required": [ + "version", + "bot_token", + "chat_id", + "intval", + ], + }; + +} + diff --git a/source/main.ts b/source/main.ts new file mode 100644 index 0000000..03969c8 --- /dev/null +++ b/source/main.ts @@ -0,0 +1,164 @@ +namespace _lixer_event_reminder +{ + + /** + */ + export async function main( + args_raw : Array + ): Promise + { + // args + const arg_handler : lib_plankton.args.class_handler = new lib_plankton.args.class_handler( + { + "action": lib_plankton.args.class_argument.positional({ + "index": 0, + "type": lib_plankton.args.enum_type.string, + "mode": lib_plankton.args.enum_mode.replace, + "default": "run", + "info": "what to do : help | fetch | send | run", + "name": "action", + }), + "conf_path": lib_plankton.args.class_argument.volatile({ + "indicators_long": ["conf-path"], + "indicators_short": ["c"], + "type": lib_plankton.args.enum_type.string, + "mode": lib_plankton.args.enum_mode.replace, + "default": "conf.json", + "info": "path to configuration file", + "name": "conf-path", + }), + "message": lib_plankton.args.class_argument.volatile({ + "indicators_long": ["message"], + "indicators_short": ["m"], + "type": lib_plankton.args.enum_type.string, + "mode": lib_plankton.args.enum_mode.replace, + "default": "test", + "info": "message to send", + "name": "message", + }), + "help": lib_plankton.args.class_argument.volatile({ + "indicators_long": ["help"], + "indicators_short": ["h"], + "type": lib_plankton.args.enum_type.boolean, + "mode": lib_plankton.args.enum_mode.replace, + "default": false, + "info": "alias for action 'help'", + "name": "help", + }), + } + ); + const args : Record = arg_handler.read( + lib_plankton.args.enum_environment.cli, + args_raw.join(" ") + ); + + // init + const conf : _lixer_event_reminder.conf.type_conf = await lib_plankton.conf.load<_lixer_event_reminder.conf.type_conf>( + _lixer_event_reminder.conf.schema, + args.conf_path + ); + + // exec + if (args.help || (args.action === "help")) { + process.stdout.write( + arg_handler.generate_help( + { + "programname": "lixer-event-reminder", + "description": "a telegram bot, which sends reminders about upcoming events", + "executable": "node build/event-reminder", + } + ) + ); + } + else { + switch (args.action) { + default: { + throw (new Error("unhandled action: " + args.action)); + break; + } + case "fetch": { + const updates : Array = await lib_plankton.telegram.bot_call_get_updates( + conf.bot_token + ); + process.stdout.write(JSON.stringify(updates, undefined, "\t") + "\n"); + break; + } + case "send": { + for (const target of conf.targets) { + const message = await lib_plankton.telegram.bot_call_send_message( + conf.bot_token, + target.chat_id, + args.message + ); + } + break; + } + case "run": { + const sources : Array<_lixer_event_reminder.type_source> = conf.sources.map( + source_raw => _lixer_event_reminder.sources.factory(source_raw) + ); + const targets : Array<_lixer_event_reminder.type_target> = conf.targets.map( + target_raw => target_raw + ); + const now : lib_plankton.pit.type_pit = lib_plankton.pit.now(); + + const events : Array<_lixer_event_reminder.type_event> = ( + (await Promise.all(sources.map(source => source.fetch()))) + .reduce((x, y) => x.concat(y), []) + ); + for (const event of events) { + const begin : lib_plankton.pit.type_pit = lib_plankton.pit.from_datetime(event.begin); + for (const target of targets) { + for (const hours of target.interval) { + const remind : boolean = lib_plankton.pit.is_between( + lib_plankton.pit.shift_hour(begin, hours), + now, + /** + * @todo parametrize window + */ + lib_plankton.pit.shift_hour(now, +24) + ); + if (remind) { + lib_plankton.log._info( + "remind", + { + "details": { + "event": event, + "target": target, + } + } + ); + /** + * @todo activate + * @todo format better + */ + const message = await lib_plankton.telegram.bot_call_send_message( + conf.bot_token, + target.chat_id, + lib_plankton.string.coin( + "{{title}} | {{begin}}", + { + "title": event.title, + "begin": lib_plankton.pit.datetime_format(event.begin), + } + ) + ); + } + } + } + } + + break; + } + } + } + + return Promise.resolve(undefined); + } +} + +_lixer_event_reminder.main(process.argv.slice(2)) + .then(() => {}) + .catch((reason) => {process.stderr.write(String(reason) + "\n");}) +; + diff --git a/source/sources/_functions.ts b/source/sources/_functions.ts new file mode 100644 index 0000000..7965815 --- /dev/null +++ b/source/sources/_functions.ts @@ -0,0 +1,28 @@ +namespace _lixer_event_reminder.sources +{ + + /** + */ + export function factory( + description : { + kind : string, + data : any + } + ) : type_source + { + switch (description.kind) { + default: { + throw (new Error("unhandled source kind: " + description.kind)); + break; + } + case "kalender_digital": { + return _lixer_event_reminder.sources.kalender_digital.implementation_source( + description.data as _lixer_event_reminder.sources.kalender_digital.type_parameters + ); + return + } + } + } + +} + diff --git a/source/sources/kalender_digital.ts b/source/sources/kalender_digital.ts new file mode 100644 index 0000000..89cd5f8 --- /dev/null +++ b/source/sources/kalender_digital.ts @@ -0,0 +1,92 @@ +namespace _lixer_event_reminder.sources.kalender_digital +{ + + /** + */ + export type type_parameters = { + id : string; + filtration : { + category_blacklist : Array; + title_blacklist : Array; + }; + }; + + + /** + */ + async function fetch( + parameters : type_parameters + ) : Promise> + { + const http_request : lib_plankton.http.type_request = { + "scheme": "https", + "host": "export.kalender.digital", + "path": lib_plankton.string.coin( + "/ics/0/{{id}}/gesamterkalender.ics", + { + "id": parameters.id, + } + ), + "version": "HTTP/2", + "method": lib_plankton.http.enum_method.get, + "query": lib_plankton.string.coin( + "?past_months={{past_months}}&future_months={{future_months}}", + { + "past_months": (0).toFixed(0), + "future_months": (2).toFixed(0), + } + ), + "headers": {}, + "body": null, + }; + const http_response : lib_plankton.http.type_response = await lib_plankton.http.call(http_request); + const ics : string = http_response.body.toString(); + const vcalendar : lib_plankton.ical.type_vcalendar = lib_plankton.ical.ics_decode(ics); + const events : Array<_lixer_event_reminder.type_event> = ( + vcalendar.vevents + .filter( + vevent => ( + vevent.categories.every(category => ! parameters.filtration.category_blacklist.includes(category)) + && + parameters.filtration.title_blacklist.every(title => ! vevent.summary.toLowerCase().includes(title.toLowerCase())) + ) + ) + .map( + vevent => { + const begin : lib_plankton.pit.type_datetime = { + "timezone_shift": 0, + "date": vevent.dtstart.value.date, + "time": vevent.dtstart.value.time, + }; + const end : lib_plankton.pit.type_datetime = { + "timezone_shift": 0, + "date": vevent.dtend.value.date, + "time": vevent.dtend.value.time, + }; + const event : _lixer_event_reminder.type_event = { + "title": vevent.summary, + "begin": begin, + "end": end, + "location": vevent.location, + }; + return event; + } + ) + ); + return events; + } + + + /** + */ + export function implementation_source( + parameters : type_parameters + ) : _lixer_event_reminder.type_source + { + return { + "fetch": () => fetch(parameters), + }; + } + +} + diff --git a/source/types.ts b/source/types.ts new file mode 100644 index 0000000..12c4848 --- /dev/null +++ b/source/types.ts @@ -0,0 +1,29 @@ +namespace _lixer_event_reminder +{ + + /** + */ + export type type_event = { + title : string; + begin : lib_plankton.pit.type_datetime, + end : (null | lib_plankton.pit.type_datetime), + location : (null | string); + }; + + + /** + */ + export type type_source = { + fetch : (() => Promise>); + }; + + + /** + */ + export type type_target = { + chat_id : int; + interval : Array; + }; + +} + diff --git a/tools/build b/tools/build new file mode 100755 index 0000000..a996492 --- /dev/null +++ b/tools/build @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 + +import os as _os +import argparse as _argparse + + +def main(): + argument_parser = _argparse.ArgumentParser( + ) + args = argument_parser.parse_args() + + if True: + _os.system("make -f tools/makefile") + + +main() diff --git a/tools/clear b/tools/clear new file mode 100755 index 0000000..89bbb94 --- /dev/null +++ b/tools/clear @@ -0,0 +1,5 @@ +#!/usr/bin/env sh + +rm -r -f temp +rm -r -f build + diff --git a/tools/deploy b/tools/deploy new file mode 100755 index 0000000..4801427 --- /dev/null +++ b/tools/deploy @@ -0,0 +1,18 @@ +#!/usr/bin/env sh + +## args + +# if [ $# -ge 1 ] ; then target=$1 ; else target="pv-svartalfheim-user:~/skripte" ; fi +target=$1 + + +## exec + +rsync \ + --recursive \ + --update \ + --delete \ + --verbose \ + --rsh=ssh \ + build/ \ + ${target} diff --git a/tools/makefile b/tools/makefile new file mode 100644 index 0000000..fb3e44a --- /dev/null +++ b/tools/makefile @@ -0,0 +1,40 @@ +## commands + +cmd_mkdir := mkdir -p +cmd_cp := cp -r -u +cmd_tsc := tsc +cmd_log := echo "--" +cmd_cat := cat +cmd_echo := echo +cmd_chmod := chmod + + +## rules + +.PHONY: _default +_default: _root + +temp/termine-reminder-unlinked.js: \ + libs/plankton/plankton.d.ts \ + source/types.ts \ + source/sources/kalender_digital.ts \ + source/sources/_functions.ts \ + source/conf.ts \ + source/main.ts + @ ${cmd_log} "compiling logic …" + @ ${cmd_mkdir} temp + @ ${cmd_tsc} $^ --lib es2020,dom --target es6 --outFile $@ + +build/termine-reminder: libs/plankton/plankton.js temp/termine-reminder-unlinked.js + @ ${cmd_log} "linking …" + @ ${cmd_echo} "#!/usr/bin/env node" > temp/head.js + @ ${cmd_mkdir} build + @ ${cmd_cat} temp/head.js $^ > $@ + @ ${cmd_chmod} +x $@ + +.PHONY: sources +sources: build/termine-reminder + +.PHONY: _root +_root: sources + diff --git a/tools/update-plankton b/tools/update-plankton new file mode 100755 index 0000000..a22bbb5 --- /dev/null +++ b/tools/update-plankton @@ -0,0 +1,23 @@ +#!/usr/bin/env sh + +## consts + +dir="libs/plankton" + + +## vars + +modules="" +modules="${modules} pit" +modules="${modules} http" +modules="${modules} ical" +modules="${modules} telegram" +modules="${modules} conf" +modules="${modules} args" + + +## exec + +mkdir -p ${dir} +cd ${dir} +ptk bundle node ${modules}