From 6e0ff082341d20efaa327b6e51593dde17f2acaf Mon Sep 17 00:00:00 2001 From: Fenris Wolf Date: Thu, 20 Feb 2025 09:12:08 +0100 Subject: [PATCH] [int] --- lib/plankton/plankton.d.ts | 1555 ++++++++----- lib/plankton/plankton.js | 4238 +++++++++++++++++++++++++----------- misc/backup.js | 218 ++ misc/conf-example.mmr.json | 34 + misc/conf.json | 48 + misc/setup-client.sh | 9 + misc/setup-server.sh | 17 + source/main.ts | 497 ++++- tools/update-plankton | 1 + 9 files changed, 4637 insertions(+), 1980 deletions(-) create mode 100644 misc/backup.js create mode 100644 misc/conf-example.mmr.json create mode 100644 misc/conf.json create mode 100644 misc/setup-client.sh create mode 100644 misc/setup-server.sh diff --git a/lib/plankton/plankton.d.ts b/lib/plankton/plankton.d.ts index 31ba994..1228080 100644 --- a/lib/plankton/plankton.d.ts +++ b/lib/plankton/plankton.d.ts @@ -227,6 +227,12 @@ declare namespace lib_plankton.base { /** */ 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 { /** @@ -290,419 +296,6 @@ declare module lib_plankton.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; -} -declare namespace lib_plankton.call { - /** - */ - class CancellablePromise extends Promise { - /** - */ - private cancelled; - /** - */ - private interval; - /** - */ - private subject; - /** - */ - constructor(executor: ((resolve: any, reject: any) => void)); - /** - */ - private clear; - /** - */ - then(onfulfilled?: ((value: type_result) => (type_next_resolved | PromiseLike)), onrejected?: ((reason: any) => (type_next_rejected | PromiseLike))): Promise; - /** - */ - catch(x: any): Promise; - /** - */ - cancel(): void; - } -} -/** - * 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 - */ - function args2list(args: any): Array; - /** - * just the empty function; useful for some callbacks etc. - * - * @author fenris - */ - function nothing(): void; - /** - * just the identity; useful for some callbacks etc.; defined as function instead of const for using type parameters - * - * @author fenris - */ - function id(x: type_value): type_value; - /** - * just the identity; useful for some callbacks etc. - * - * @author fenris - */ - 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 - */ - 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 - */ - function curryfy(f: Function): Function; - /** - * @author fenris - */ - function convey(value: any, functions: Array): any; - /** - * @author fenris - */ - function timeout(procedure: (() => void), delay_in_seconds: float): int; - /** - * Promise version of "setTimeout" - * - * @author fenris - */ - function defer(seconds: float, action: (() => type_result)): Promise; - /** - * a definition for a value being "defined" - * - * @author neuc - */ - 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 - */ - 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 - */ - 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 - */ - function method(name: string): ((object: type_object) => type_output); - /** - * @author fenris - */ - type type_coproduct = { - kind: string; - data?: any; - }; - /** - * @author fenris - */ - function distinguish(coproduct: type_coproduct, handlers: Record type_output)>, options?: { - fallback?: (null | ((coproduct?: type_coproduct) => type_output)); - }): type_output; - /** - * for rate_limit_check - * - * @author fenris - */ - type type_mana_snapshot = { - timestamp: float; - value: float; - }; - /** - * rate limiting algorithm, based on the idea of mana (magic power) in video games: - * - an actor has a fixed mana capacity, i.e. the maximum amount of available power - * - an actor has a fixed rate of mana regeneration, i.e. how fast the power is filled up (linear growth) - * - an action has a defined mana heft, i.e. how much power is required and deducted in order to execute it - * - mana states are represented by snapshots, i.e. the amount of power at a certain point in time - * - * @author fenris - */ - function rate_limit_check(setup: { - capacity: float; - regeneration_rate: float; - get_snapshot: (() => Promise<(null | type_mana_snapshot)>); - set_snapshot: ((snapshot: type_mana_snapshot) => Promise); - update_snapshot: ((timestamp: float, value_increment: float) => Promise); - }, heft: float): Promise<{ - granted: boolean; - seconds: (null | float); - }>; -} -declare namespace lib_plankton.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.code { /** * @author fenris @@ -930,6 +523,393 @@ declare namespace lib_plankton.json { decode(x: string): any; } } +/** + * 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.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.email { /** */ @@ -950,183 +930,647 @@ declare namespace lib_plankton.log { warning = 3, error = 4 } - /** - */ - function level_order(level1: enum_level, level2: enum_level): boolean; - /** - */ - function level_show(level: enum_level): string; /** */ type type_entry = { level: enum_level; incident: string; - details: Record; + tags: Array; + details: any; }; -} -/** - * @deprecated - * @todo remove - */ -declare namespace lib_plankton.log { - function level_push(level: int): void; - function level_pop(): void; - function indent_push(indent: int): void; - function indent_pop(): void; - function indent_inc(): void; - function indent_dec(): void; /** - * @author fenris */ - function write({ "message": message, "type": type, "prefix": prefix, "level": level, "indent": indent, }: { - message?: string; - type?: string; - prefix?: string; - level?: int; - indent?: int; - }): void; + 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 { /** */ - abstract class class_channel { - /** - */ - abstract add(entry: type_entry): void; - } + 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 { /** - * output for writing log entries to stdout + * @todo use label */ - class class_channel_stdout extends class_channel { - /** - */ - add(entry: type_entry): void; - } -} -declare namespace lib_plankton.log { + function get_logger_logic(logger_data: type_logger_data): type_logger_logic; /** */ - class class_channel_file extends class_channel { - /** - * the path of the log file - */ - private path; - /** - */ - private human_readable; - /** - * [constructor] - */ - constructor(path: string, human_readable: boolean); - /** - */ - add(entry: type_entry): void; - } -} -declare namespace lib_plankton.log { + function format_entry(format_definition: type_format_definition, entry: type_entry): string; /** */ - class class_channel_email extends class_channel { + 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 */ - private smtp_credentials; + 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 */ - private sender; - /** - */ - private receivers; - /** - * [constructor] - */ - constructor(smtp_credentials: { + 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); - /** - */ - add(entry: type_entry): void; - } -} -declare namespace lib_plankton.log { - /** - * output for desktop notifications via "libnotify" - */ - class class_channel_notify extends class_channel { - /** - */ - add(entry: type_entry): void; - } -} -declare namespace lib_plankton.log { - /** - * decorator for filtering out log entries below a certain level threshold - */ - class class_channel_minlevel extends class_channel { - /** - */ - private core; - /** - */ - private threshold; - /** - */ - constructor(core: class_channel, threshold: enum_level); - /** - */ - add(entry: type_entry): void; - } -} -declare namespace lib_plankton.log { - /** - */ - function channel_make(description: { - kind: string; - data?: { - [key: string]: any; }; - }): class_channel; + sender: string; + receivers: Array; + }; + /** + * @todo tags + */ + function send(subject: type_subject, entry: type_entry): void; /** */ - type type_configuration = Array; - /** - */ - function conf_default(): type_configuration; + function logic(subject: type_subject): type_channel_logic; } declare namespace lib_plankton.log { /** - * pushes a new configuration on the stack and activates it */ - function conf_push(channels: type_configuration): void; - /** - * pops the current active configuration from the stack - */ - function conf_pop(): void; - /** - * consumes a log entry, i.e. sends it to the currently active outputs - */ - function add(entry: type_entry): void; - /** - */ - function debug(incident: string, details?: Record): void; - /** - */ - function info(incident: string, details?: Record): void; - /** - */ - function notice(incident: string, details?: Record): void; - /** - */ - function warning(incident: string, details?: Record): void; - /** - */ - function error(incident: string, details?: Record): void; + 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 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 var plain_text_to_html: (text: string) => string; /** @@ -1164,7 +1608,7 @@ declare namespace lib_plankton.string { * @return {Array} * @author fenris */ - function split(chain: string, separator?: string): Array; + function split(chain: string, separator: string): Array; /** * @author neu3no */ @@ -1250,6 +1694,9 @@ declare namespace lib_plankton.string { /** */ function slice(str: string, size: int): Array; + /** + */ + function capitalize(str: string): string; } /** * @deprecated diff --git a/lib/plankton/plankton.js b/lib/plankton/plankton.js index 86be455..5b1ab5a 100644 --- a/lib/plankton/plankton.js +++ b/lib/plankton/plankton.js @@ -1,18 +1,3 @@ -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); /* This file is part of »bacterio-plankton:base«. @@ -115,7 +100,7 @@ along with »bacterio-plankton:base«. If not, see this.actions[id](information)); } - }; + } /** * @author frac */ - class_observer.prototype.rollout = function () { - var _this = this; - this.buffer.forEach(function (information) { return _this.notify(information, false); }); + rollout() { + this.buffer.forEach(information => this.notify(information, false)); this.buffer = []; - }; - return class_observer; -}()); + } +} /** * @author frac */ @@ -389,27 +369,23 @@ along with »bacterio-plankton:base«. If not, see x.toString()).join(",") + "]")); + } +} /* This file is part of »bacterio-plankton:base«. @@ -438,9 +414,8 @@ var lib_plankton; * * @author fenris */ - function get_current_timestamp(rounded) { - if (rounded === void 0) { rounded = false; } - var x = (Date.now() / 1000); + function get_current_timestamp(rounded = false) { + const x = (Date.now() / 1000); return (rounded ? Math.round(x) : x); ; } @@ -451,6 +426,24 @@ var lib_plankton; 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 = {})); /* @@ -599,6 +592,550 @@ var lib_plankton; })(pod = lib_plankton.pod || (lib_plankton.pod = {})); })(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:call«. Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' @@ -776,89 +1313,6 @@ 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) { - /** - */ - class CancellablePromise extends Promise { - /** - */ - constructor(executor) { - super((resolve, reject) => { }); - this.subject = (new Promise((resolve, reject) => { - Promise.race([ - new Promise(executor), - new Promise((resolve_, reject_) => { - this.interval = setInterval(() => { - if (!this.cancelled) { - // do nothing - } - else { - reject_(new Error("cancelled")); - this.clear(); - } - }, 0); - }), - ]) - .then(resolve, reject); - })); - this.cancelled = false; - this.interval = null; - } - /** - */ - clear() { - if (this.interval === null) { - // do nothing - } - else { - clearInterval(this.interval); - this.interval = null; - } - } - /** - */ - then(onfulfilled, onrejected) { - this.clear(); - return this.subject.then(onfulfilled, onrejected); - } - /** - */ - catch(x) { - this.clear(); - return this.subject.catch(x); - } - /** - */ - cancel() { - this.cancelled = true; - this.clear(); - } - } - call.CancellablePromise = CancellablePromise; - })(call = lib_plankton.call || (lib_plankton.call = {})); -})(lib_plankton || (lib_plankton = {})); -/* -This file is part of »bacterio-plankton:call«. - -Copyright 2016-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 . */ @@ -1388,6 +1842,31 @@ var lib_plankton; 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 */ @@ -1494,63 +1973,36 @@ var lib_plankton; } call.distinguish = distinguish; /** - * rate limiting algorithm, based on the idea of mana (magic power) in video games: - * - an actor has a fixed mana capacity, i.e. the maximum amount of available power - * - an actor has a fixed rate of mana regeneration, i.e. how fast the power is filled up (linear growth) - * - an action has a defined mana heft, i.e. how much power is required and deducted in order to execute it - * - mana states are represented by snapshots, i.e. the amount of power at a certain point in time - * - * @author fenris */ - async function rate_limit_check(setup, heft) { - if (heft > setup.capacity) { - return Promise.resolve({ - "granted": false, - "seconds": null, - }); + function try_catch_wrap(get_value) { + try { + return { + "value": get_value(), + "error": null, + }; } - else { - // get current value - const current_timestamp = (Date.now() / 1000); - const old_snapshot_raw = (await setup.get_snapshot()); - const old_snapshot = (old_snapshot_raw - ?? - { "timestamp": current_timestamp, "value": setup.capacity }); - const seconds_passed = (current_timestamp - old_snapshot.timestamp); - const current_value = Math.min(setup.capacity, (old_snapshot.value - + - (setup.regeneration_rate - * - seconds_passed))); - // analyze - if (current_value < heft) { - // too less - const seconds_needed = ((setup.regeneration_rate <= 0) - ? null - : ((heft - old_snapshot.value) / setup.regeneration_rate)); - return Promise.resolve({ - "granted": false, - "seconds": ((seconds_needed === null) ? null : (seconds_needed - seconds_passed)), - }); - } - else { - // enough -> update snapshot - const new_value = (current_value - heft); - // set_snapshot - if (old_snapshot_raw === null) { - await setup.set_snapshot({ "timestamp": current_timestamp, "value": new_value }); - } - else { - await setup.update_snapshot(current_timestamp, (new_value - old_snapshot.value)); - } - return Promise.resolve({ - "granted": true, - "seconds": 0, - }); - } + catch (error) { + return { + "value": null, + "error": error, + }; } } - call.rate_limit_check = rate_limit_check; + 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 = {})); /* @@ -1709,550 +2161,6 @@ var lib_plankton; file.delete_ = delete_; })(file = lib_plankton.file || (lib_plankton.file = {})); })(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 = {})); 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) { @@ -2347,21 +2255,6 @@ var lib_plankton; email.send = send; })(email = lib_plankton.email || (lib_plankton.email = {})); })(lib_plankton || (lib_plankton = {})); -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); /* This file is part of »bacterio-plankton:log«. @@ -2396,6 +2289,31 @@ var lib_plankton; 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) { @@ -2404,469 +2322,33 @@ var lib_plankton; log.level_order = level_order; /** */ - function level_show(level) { - switch (level) { - case enum_level.debug: return "debug"; - case enum_level.info: return "info"; - case enum_level.notice: return "notice"; - case enum_level.warning: return "warning"; - case enum_level.error: return "error"; - default: return "(unknown)"; + 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; - })(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:lang«. If not, see . - */ -/** - * @deprecated - * @todo remove - */ -var lib_plankton; -(function (lib_plankton) { - var log; - (function (log) { - /** - * @author fenris - */ - /*export*/ var level_stack = [0]; - function level_push(level) { level_stack.push(level); } - log.level_push = level_push; - function level_pop() { if (level_stack.length > 1) { - level_stack.pop(); - } } - log.level_pop = level_pop; - function level_get() { return level_stack.slice(-1)[0]; } - /* - export function level_inc() : void {level_push(level_get()+1);} - export function level_dec() : void {level_push(level_get()-1);} - */ - /** - * @author fenris - */ - var indent_stack = [0]; - function indent_push(indent) { indent_stack.push(indent); } - log.indent_push = indent_push; - function indent_pop() { if (indent_stack.length > 1) { - indent_stack.pop(); - } } - log.indent_pop = indent_pop; - function indent_get() { return level_stack.slice(-1)[0]; } - function indent_inc() { level_push(level_get() + 1); } - log.indent_inc = indent_inc; - function indent_dec() { level_push(level_get() - 1); } - log.indent_dec = indent_dec; - /** - * @author fenris - */ - function write(_a) { - var message = _a["message"], _b = _a["type"], type = _b === void 0 ? null : _b, _c = _a["prefix"], prefix = _c === void 0 ? null : _c, _d = _a["level"], level = _d === void 0 ? 0 : _d, _e = _a["indent"], indent = _e === void 0 ? 0 : _e; - var entry = { - "level": ((type === null) - ? lib_plankton.log.enum_level.info - : { - "debug": lib_plankton.log.enum_level.debug, - "info": lib_plankton.log.enum_level.info, - "notice": lib_plankton.log.enum_level.notice, - "warning": lib_plankton.log.enum_level.warning, - "error": lib_plankton.log.enum_level.error - }[type]), - "incident": message, - "details": { - "prefix": prefix, - "level": level, - "indent": indent - } - }; - lib_plankton.log.add(entry); - } - log.write = write; - })(log = lib_plankton.log || (lib_plankton.log = {})); -})(lib_plankton || (lib_plankton = {})); -/* -This file is part of »bacterio-plankton:log«. - -Copyright 2016-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 class_channel = /** @class */ (function () { - function class_channel() { - } - return class_channel; - }()); - log.class_channel = class_channel; - })(log = lib_plankton.log || (lib_plankton.log = {})); -})(lib_plankton || (lib_plankton = {})); -/* -This file is part of »bacterio-plankton:log«. - -Copyright 2016-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) { - /** - * output for writing log entries to stdout - */ - var class_channel_stdout = /** @class */ (function (_super) { - __extends(class_channel_stdout, _super); - function class_channel_stdout() { - return _super !== null && _super.apply(this, arguments) || this; - } - /** - */ - class_channel_stdout.prototype.add = function (entry) { - process.stdout.write(("<" + (new Date(Date.now())).toISOString().slice(0, 19) + ">") - + - " " - + - ("[" + log.level_show(entry.level) + "]") - + - " " - + - ("" + entry.incident + "") - + - ": " - + - JSON.stringify(entry.details, undefined, " ") - + - "\n"); - }; - return class_channel_stdout; - }(log.class_channel)); - log.class_channel_stdout = class_channel_stdout; - })(log = lib_plankton.log || (lib_plankton.log = {})); -})(lib_plankton || (lib_plankton = {})); -/* -This file is part of »bacterio-plankton:log«. - -Copyright 2016-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 class_channel_file = /** @class */ (function (_super) { - __extends(class_channel_file, _super); - /** - * [constructor] - */ - function class_channel_file(path, human_readable) { - var _this = _super.call(this) || this; - _this.path = path; - _this.human_readable = human_readable; - return _this; - } - /** - */ - class_channel_file.prototype.add = function (entry) { - var _this = this; - var nm_fs = require("fs"); - var line = (this.human_readable - ? (("<" + (new Date(Date.now())).toISOString().slice(0, 19) + ">") - + - " " - + - ("[" + log.level_show(entry.level) + "]") - + - " " - + - ("" + entry.incident + "") - + - ": " - + - JSON.stringify(entry.details, undefined, " ") - + - "\n") - : (JSON.stringify({ - "timestamp": lib_plankton.base.get_current_timestamp(), - "level_number": entry.level, - "level_name": log.level_show(entry.level), - "incident": entry.incident, - "details": entry.details - }) - + - "\n")); - nm_fs.writeFile(this.path, line, { - "flag": "a+" - }, function (error) { - if (error !== null) { - process.stderr.write('-- [plankton] could not add log entry to file ' + _this.path + "\n"); - } - else { - // do nothing - } - }); - }; - return class_channel_file; - }(log.class_channel)); - log.class_channel_file = class_channel_file; - })(log = lib_plankton.log || (lib_plankton.log = {})); -})(lib_plankton || (lib_plankton = {})); -/* -This file is part of »bacterio-plankton:log«. - -Copyright 2016-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 class_channel_email = /** @class */ (function (_super) { - __extends(class_channel_email, _super); - /** - * [constructor] - */ - function class_channel_email(smtp_credentials, sender, receivers) { - var _this = _super.call(this) || this; - _this.smtp_credentials = smtp_credentials; - _this.sender = sender; - _this.receivers = receivers; - return _this; - } - /** - */ - class_channel_email.prototype.add = function (entry) { - var nm_fs = require("fs"); - lib_plankton.email.send(this.smtp_credentials, this.sender, this.receivers, (("[" + log.level_show(entry.level) + "]") - + - " " - + - ("" + entry.incident + "")), JSON.stringify(entry.details, undefined, " ")); - }; - return class_channel_email; - }(log.class_channel)); - log.class_channel_email = class_channel_email; - })(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) { - /** - * output for desktop notifications via "libnotify" - */ - var class_channel_notify = /** @class */ (function (_super) { - __extends(class_channel_notify, _super); - function class_channel_notify() { - return _super !== null && _super.apply(this, arguments) || this; - } - /** - */ - class_channel_notify.prototype.add = function (entry) { - var nm_child_process = require("child_process"); - var command = ("notify-send" - + - " " - + - ("'" - + - ("[" + log.level_show(entry.level) + "]") - + - " " - + - entry.incident - + - "'") - + - " " - + - ("'" - + - (Object.keys(entry.details) - .map(function (key) { return (key + ": " + JSON.stringify(entry.details[key])); }) - .join("\n")) - + - "'")); - nm_child_process.exec(command, function (error, stdout, stderr) { - // do noting - }); - }; - return class_channel_notify; - }(log.class_channel)); - log.class_channel_notify = class_channel_notify; - })(log = lib_plankton.log || (lib_plankton.log = {})); -})(lib_plankton || (lib_plankton = {})); -/* -This file is part of »bacterio-plankton:log«. - -Copyright 2016-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) { - /** - * decorator for filtering out log entries below a certain level threshold - */ - var class_channel_minlevel = /** @class */ (function (_super) { - __extends(class_channel_minlevel, _super); - /** - */ - function class_channel_minlevel(core, threshold) { - var _this = _super.call(this) || this; - _this.core = core; - _this.threshold = threshold; - return _this; - } - /** - */ - class_channel_minlevel.prototype.add = function (entry) { - if (!log.level_order(this.threshold, entry.level)) { - // do nothing - } - else { - this.core.add(entry); - } - }; - return class_channel_minlevel; - }(log.class_channel)); - log.class_channel_minlevel = class_channel_minlevel; - })(log = lib_plankton.log || (lib_plankton.log = {})); -})(lib_plankton || (lib_plankton = {})); -/* -This file is part of »bacterio-plankton:log«. - -Copyright 2016-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 translate_level(level_string) { + function level_decode(level_string) { return { "debug": log.enum_level.debug, "info": log.enum_level.info, @@ -2875,43 +2357,468 @@ var lib_plankton; "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 channel_make(description) { - var _a, _b, _c, _d, _e; - switch (description.kind) { + 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 log channel kind: " + description.kind)); - break; - } - case "stdout": { - return (new log.class_channel_minlevel(new log.class_channel_stdout(), translate_level((_a = description.data["threshold"]) !== null && _a !== void 0 ? _a : "debug"))); - break; - } - case "file": { - return (new log.class_channel_minlevel(new log.class_channel_file(((_b = description.data["path"]) !== null && _b !== void 0 ? _b : "/tmp/plankton.log"), false), translate_level((_c = description.data["threshold"]) !== null && _c !== void 0 ? _c : "debug"))); - break; - } - case "email": { - return (new log.class_channel_minlevel(new log.class_channel_email(description.data["smtp_credentials"], description.data["sender"], description.data["receivers"]), translate_level((_d = description.data["threshold"]) !== null && _d !== void 0 ? _d : "debug"))); - break; - } - case "notify": { - return (new log.class_channel_minlevel(new log.class_channel_notify(), translate_level((_e = description.data["threshold"]) !== null && _e !== void 0 ? _e : "debug"))); + throw (new Error("unhandled format kind: " + format_definition["kind"])); break; } } } - log.channel_make = channel_make; + log.format_entry = format_entry; /** */ - function conf_default() { - return [ - new log.class_channel_minlevel(new log.class_channel_stdout(), log.enum_level.notice), - new log.class_channel_minlevel(new log.class_channel_notify(), log.enum_level.error), - ]; + 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.conf_default = conf_default; + 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 = {})); /* @@ -2939,120 +2846,1812 @@ var lib_plankton; (function (log) { /** */ - var _channel_stack = null; - /** - * pushes a new configuration on the stack and activates it - */ - function conf_push(channels) { - if (_channel_stack === null) { - _channel_stack = []; - } - _channel_stack.push(channels); - } - log.conf_push = conf_push; - /** - * pops the current active configuration from the stack - */ - function conf_pop() { - if (_channel_stack.length > 0) { - _channel_stack.pop(); - } - else { - // do nothing + 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.conf_pop = conf_pop; + 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) { /** - * makes the logging system ready */ - function setup() { - if (_channel_stack === null) { - _channel_stack = []; - conf_push(log.conf_default()); - } - else { - // do nothing - } + 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()); } /** - * consumes a log entry, i.e. sends it to the currently active outputs */ - function add(entry) { - setup(); - _channel_stack.slice(-1)[0].forEach(function (channel) { return channel.add(entry); }); + function get_main_logger_logic() { + return lib_plankton.log.get_logger_logic(get_main_logger()); } - log.add = add; /** + * consumes a log entry, i.e. sends it to all channels */ - function debug(incident, details) { - if (details === void 0) { details = {}; } - add({ "level": log.enum_level.debug, "incident": incident, "details": details }); + 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) { - if (details === void 0) { details = {}; } - add({ "level": log.enum_level.info, "incident": incident, "details": details }); + 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) { - if (details === void 0) { details = {}; } - add({ "level": log.enum_level.notice, "incident": incident, "details": details }); + 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) { - if (details === void 0) { details = {}; } - add({ "level": log.enum_level.warning, "incident": incident, "details": details }); + 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) { - if (details === void 0) { details = {}; } - add({ "level": log.enum_level.error, "incident": incident, "details": details }); + 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:log«. +This file is part of »bacterio-plankton:object«. Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' -»bacterio-plankton:log« is free software: you can redistribute it and/or modify +»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:lang« is distributed in the hope that it will be useful, +»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:log«. If not, see . +along with »bacterio-plankton:object«. If not, see . */ var lib_plankton; (function (lib_plankton) { - var log; - (function (log) { + 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; /** */ - log.conf_push([ - log.channel_make({ - "kind": "stdout", - "data": { - "threshold": "info" + 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 + }); } - }), - ]); - })(log = lib_plankton.log || (lib_plankton.log = {})); + 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:string«. @@ -3263,6 +4862,7 @@ var lib_plankton; */ 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 { @@ -3289,7 +4889,7 @@ var lib_plankton; * @return {Array} * @author fenris */ - function split(chain, separator = " ") { + function split(chain, separator) { if (chain.length == 0) { return []; } @@ -3493,11 +5093,16 @@ var lib_plankton; 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, - }); + /* + lib_plankton.log.debug( + "lib_plankton.string.coin", + { + "key": key, + "regex": regexp_argument.toString(), + "value": value, + } + ); + */ str = str.replace(regexp_argument, value); } } @@ -3505,11 +5110,16 @@ var lib_plankton; { 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, - }); + /* + lib_plankton.log.debug( + "lib_plankton.string.coin", + { + "key": key, + "regex": regexp_argument.toString(), + "value": value, + } + ); + */ str = str.replace(regexp_argument, value); } }); @@ -3553,6 +5163,12 @@ var lib_plankton; 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 = {})); /** diff --git a/misc/backup.js b/misc/backup.js new file mode 100644 index 0000000..a05c6f7 --- /dev/null +++ b/misc/backup.js @@ -0,0 +1,218 @@ +#!/usr/bin/env nodejs + + +function string_coin( + template, + arguments_ +) +{ + let result = template; + Object.entries(arguments_).forEach( + ([key, value]) => { + result = result.replace(new RegExp("{{" + key + "}}", "g"), value); + } + ); + return result; +} + + +function borg_init( + repository_directory, + { + "encryption": encryption = "none", + } = { + } +) +{ + return string_coin( + "borg init --encryption={{encryption}} {{repository_directory}}\n", + { + "repository_directory": repository_directory, + "encryption": encryption, + } + ); +} + + +function borg_create( + repository_directory, + archive_name, + directories, + { + "compression": compression = "none", + } = { + } +) +{ + return string_coin( + "borg create --compression={{compression}} {{repository_directory}}::{{archive_name}} {{directories}}\n", + { + "repository_directory": repository_directory, + "archive_name": archive_name, + "compression": compression, + "directories": directories.join(" "), + } + ) +} + + +function borg_prune( + repository_directory, + age, + { + "keep_weekly": keep_weekly = null, + "keep_yearly": keep_yearly = null, + } = { + } +) +{ + return string_coin( + "borg prune --keep-within=2w{{macro_keep_weekly}}{{macro_keep_yearly}} {{repository_directory}}\n", + { + "repository_directory": repository_directory, + "keep_within": age, + "macro_keep_weekly": ((keep_weekly === null) ? "" : string_coin(" --keep-weekly={{x}}", {"x": keep_weekly.toFixed(0)})), + "macro_keep_yearly": ((keep_yearly === null) ? "" : string_coin(" --keep-yearly={{x}}", {"x": keep_yearly.toFixed(0)})), + } + ) +} + + +function get_conf( +) +{ + const _fs = require("fs"); + const conf = JSON.parse(_fs.readFileSync("conf.json")); + return conf; +} + + +function get_stamp( +) +{ + const date = (new Date(Date.now())); + return string_coin( + "{{year}}{{month}}{{day}}", + { + "year": date.getFullYear().toFixed(0).padStart(4, "0"), + "month": (date.getMonth()+1).toFixed(0).padStart(2, "0"), + "day": date.getDate().toFixed(0).padStart(2, "0"), + } + ); +} + + +function get_repository_directory( + conf +) +{ + return conf.target.data.repository; +} + + +function init( + conf +) +{ + const repository_directory = get_repository_directory(conf); + if (false) { + process.stdout.write( + string_coin( + "mkdir --parents {{repository_directory}}\n", + { + "repository_directory": repository_directory, + } + ) + ); + } + process.stdout.write( + borg_init( + repository_directory, + { + "encryption": "none", + } + ) + ); +} + + +function run( + conf, + stamp +) +{ + const repository_directory = get_repository_directory(conf); + conf.concerns.forEach( + concern => { + process.stdout.write( + string_coin( + "## {{name}}\n", + { + "name": concern.name, + } + ) + ); + process.stdout.write( + borg_create( + repository_directory, + string_coin( + "{{concern_name}}-{{stamp}}", + { + "concern_name": concern.name, + "stamp": stamp, + } + ), + [concern.source_directory], + { + "compression": conf.target.data.compression, + } + ) + ); + process.stdout.write( + borg_prune( + repository_directory, + "2w", + { + "keep_weekly": 7, + "keep_yearly": 2, + } + ) + ); + process.stdout.write( + "\n" + ); + } + ); +} + + +function main( + args +) +{ + // args + const action = (args.shift() ?? "run"); + + // exec + switch (action) { + case "init": { + const conf = get_conf(); + init(conf); + break; + } + case "run": { + const conf = get_conf(); + const stamp = get_stamp(); + run(conf, stamp); + break; + } + default: { + throw (new Error("unhandled action: " + action)); + break; + } + } +} + + +main(process.argv.slice(2)); + diff --git a/misc/conf-example.mmr.json b/misc/conf-example.mmr.json new file mode 100644 index 0000000..412ffde --- /dev/null +++ b/misc/conf-example.mmr.json @@ -0,0 +1,34 @@ +{ + "version": "1", + "target": { + "kind": "plain", + "parameters": { + "directory": "/tmp/backup" + } + }, + "concerns": [ + { + "active": true, + "name": "fehuz", + "kind": "files", + "parameters": { + "path": "/var/fehuz", + "name": "fehuz" + } + }, + { + "active": true, + "name": "uruz", + "kind": "postgresql_dump", + "parameters": { + "credentials": { + "host": "postgresql.example.org", + "username": "username", + "password": "password", + "schema": "example" + }, + "name": "uruz" + } + } + ] +} diff --git a/misc/conf.json b/misc/conf.json new file mode 100644 index 0000000..d1aea2c --- /dev/null +++ b/misc/conf.json @@ -0,0 +1,48 @@ +{ + "target": { + "kind": "borg", + "data": { + "repository": "ssh://pv-fensalir-kvasir///home/kvasir/repos/ramsch.sx", + "compression": "lz4" + } + }, + "concerns": [ + { + "name": "espe-database", + "source_directory": "/tmp/backup/espe-database" + }, + { + "name": "forgejo-database", + "source_directory": "/tmp/backup/forgejo-database" + }, + { + "name": "forgejo-files", + "source_directory": "/tmp/backup/forgejo-files" + }, + { + "name": "hedgedoc-database", + "source_directory": "/tmp/backup/hedgedoc-database" + }, + { + "name": "owncloud-files", + "source_directory": "/tmp/backup/owncloud-files" + }, + { + "name": "synapse-database", + "source_directory": "/tmp/backup/synapse-database" + }, + { + "name": "vikunja-database", + "source_directory": "/tmp/backup/vikunja-database" + }, + { + "name": "wiki_js-database", + "source_directory": "/tmp/backup/wiki_js-database" + }, + { + "name": "zeitbild-files", + "source_directory": "/tmp/backup/zeitbild-files" + } + ] +} + diff --git a/misc/setup-client.sh b/misc/setup-client.sh new file mode 100644 index 0000000..4414705 --- /dev/null +++ b/misc/setup-client.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env sh + +## exec + +mkdir --parents ~/.ssh/keypairs +ssh-keygen -t ed25519 -f ~/.ssh/keypairs/fensalir-kvasir + +# todo: add entry to ~/.ssh/config + diff --git a/misc/setup-server.sh b/misc/setup-server.sh new file mode 100644 index 0000000..5c6f45c --- /dev/null +++ b/misc/setup-server.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env sh + +## const + +username=kvasir +repodir=repos + + +## exec + +apt update && apt install borgbackup + +useradd ${username} --create-home --home-dir=/home/${username}/${repodir} --groups sudo +# todo: add ssh key to ~/.ssh/authorized_keys + +sudo --other-user=${username} mkdir --parents /home/${username}/${repodir} + diff --git a/source/main.ts b/source/main.ts index 843ba0c..77dd5af 100644 --- a/source/main.ts +++ b/source/main.ts @@ -1,3 +1,228 @@ + +const _conf_schema : lib_plankton.conf.type_schema = { + "nullable": false, + "type": "object", + "properties": { + "version": { + "nullable": false, + "type": "string" + }, + "target": { + "anyOf": [ + { + "nullable": false, + "type": "object", + "properties": { + "kind": { + "nullable": false, + "type": "string", + "enum": ["plain"] + }, + "parameters": { + "nullable": false, + "type": "object", + "properties": { + "directory": { + "nullable": false, + "type": "string" + }, + }, + "additionalProperties": false, + "required": [ + "directory", + ] + }, + }, + "additionalProperties": false, + "required": [ + "kind", + "parameters", + ] + }, + { + "nullable": false, + "type": "object", + "properties": { + "kind": { + "nullable": false, + "type": "string", + "enum": ["borg"] + }, + "parameters": { + "nullable": false, + "type": "object", + "properties": { + "repository": { + "nullable": false, + "type": "string" + }, + "compression": { + "nullable": false, + "type": "string", + "enum": [ + "none", + "lz4", + "zlib", + "lzma", + ], + "default": "lz4" + }, + }, + "required": [ + "repository", + ] + }, + }, + "additionalProperties": false, + "required": [ + "kind", + "parameters", + ] + } + ] + }, + /* + "defaults": { + }, + */ + "concerns": { + "nullable": false, + "type": "array", + "items": { + "anyOf": [ + { + "nullable": false, + "type": "object", + "properties": { + "active": { + "nullable": false, + "type": "boolean", + "default": true + }, + "name": { + "nullable": false, + "type": "string" + }, + "kind": { + "nullable": false, + "type": "string", + "enum": ["files"] + }, + "parameters": { + "nullable": false, + "type": "object", + "properties": { + "path": { + "nullable": false, + "type": "string", + }, + "name": { + "nullable": false, + "type": "string", + }, + }, + "additionalProperties": false, + "required": [ + "path", + "name", + ] + } + }, + "additionalProperties": false, + "required": [ + "name", + "kind", + "parameters", + ] + }, + { + "nullable": false, + "type": "object", + "properties": { + "active": { + "nullable": false, + "type": "boolean", + "default": true + }, + "name": { + "nullable": false, + "type": "string" + }, + "kind": { + "nullable": false, + "type": "string", + "enum": ["postgresql_dump"] + }, + "parameters": { + "nullable": false, + "type": "object", + "properties": { + "credentials": { + "nullable": false, + "type": "object", + "properties": { + "host": { + "nullable": false, + "type": "string", + }, + "port": { + "nullable": false, + "type": "integer", + "default": 5432 + }, + "username": { + "nullable": false, + "type": "string", + }, + "password": { + "nullable": false, + "type": "string", + }, + "schema": { + "nullable": false, + "type": "string", + }, + }, + "additionalProperties": false, + "required": [ + "host", + "username", + "password", + "schema", + ] + }, + "name": { + "nullable": false, + "type": "string", + }, + }, + "additionalProperties": false, + "required": [ + "credentials", + "name", + ] + } + }, + "additionalProperties": false, + "required": [ + "name", + "kind", + "parameters", + ] + }, + ] + } + }, + }, + "additionalProperties": false, + "required": [ + "version", + "target", + "concerns", + ] +}; + + /** */ function get_stamp(): string @@ -22,134 +247,176 @@ function get_stamp(): string */ async function main(): Promise { - const conf = lib_plankton.json.decode(await lib_plankton.file.read("conf.json")); + // const conf = lib_plankton.json.decode(await lib_plankton.file.read("conf.json")); + const conf : any = await lib_plankton.conf.load( + _conf_schema, + "conf.json" + ); const stamp: string = get_stamp(); - const target_directory = (conf.target.directory + "/" + stamp); - let commands: Array = []; - const commands_add : (command: string) => void = (command) => { - commands.push(command); - }; - const commands_apply : () => void = () => { - // TODO - process.stdout.write(commands.join("\n") + "\n"); - }; - - commands_add( - lib_plankton.string.coin( - "mkdir --parents {{directory}}", - { - "directory": target_directory, - } - ) - ); - commands_add( - "" - ); - for await (const concern of conf.concerns) { - if (! concern.active) { - // do nothing - } - else { + switch (conf.target.kind) { + case "plain": { + const target_directory = (conf.target.parameters.directory/* + "/" + stamp*/); + + let commands: Array = []; + const commands_add : (command: string) => void = (command) => { + commands.push(command); + }; + const commands_apply : () => void = () => { + // TODO + process.stdout.write(commands.join("\n") + "\n"); + }; + commands_add( lib_plankton.string.coin( - "# {{name}}", + "mkdir --parents {{directory}}", { - "name": concern.name, - "kind": concern.kind, + "directory": target_directory, } ) ); - commands_add( - lib_plankton.string.coin( - "echo '-- {{name}}' > /dev/stderr", - { - "name": concern.name, - "kind": concern.kind, - } - ) - ); - switch (concern.kind) { - case "postgresql_dump": { - const password_file_path: string = "${HOME}/.pgpass"; - commands_add( - lib_plankton.string.coin( - "echo '{{host}}:{{port}}:{{schema}}:{{username}}:{{password}}' > {{path}} && chmod 0600 {{path}}", - { - "path": password_file_path, - "host": concern.parameters.credentials.host, - "port": concern.parameters.credentials.port.toFixed(0), - "username": concern.parameters.credentials.username, - "password": concern.parameters.credentials.password, - "schema": concern.parameters.credentials.schema, - } - ) - ); - commands_add( - lib_plankton.string.coin( - "pg_dump --host={{host}} --port={{port}} --username={{username}} {{schema}} > {{target_path}}", - { - "host": concern.parameters.credentials.host, - "port": concern.parameters.credentials.port.toFixed(0), - "username": concern.parameters.credentials.username, - "schema": concern.parameters.credentials.schema, - "target_path": lib_plankton.string.coin( - "{{directory}}/{{name}}.sql", - { - "directory": target_directory, - "name": concern.parameters.name, - } - ), - } - ) - ); - commands_add( - lib_plankton.string.coin( - "rm {{path}}", - { - "path": password_file_path, - } - ) - ); - break; - } - case "files": { - commands_add( - lib_plankton.string.coin( - "tar --create --directory={{path}} . > {{target_path}}", - { - "path": concern.parameters.path, - "target_path": lib_plankton.string.coin( - "{{directory}}/{{name}}.tar", - { - "directory": target_directory, - "name": concern.parameters.name, - } - ), - } - ) - ); - break; - } - default: { - throw (new Error("unhandled kind: " + concern.kind)); - break; - } - } commands_add( "" ); + for await (const concern of conf.concerns) { + if (! concern.active) { + // do nothing + } + else { + commands_add( + lib_plankton.string.coin( + "# {{name}}", + { + "name": concern.name, + "kind": concern.kind, + } + ) + ); + commands_add( + lib_plankton.string.coin( + "echo '-- {{name}}' > /dev/stderr", + { + "name": concern.name, + "kind": concern.kind, + } + ) + ); + switch (concern.kind) { + case "files": { + commands_add( + lib_plankton.string.coin( + "mkdir --parents {{directory}}", + { + "directory": lib_plankton.string.coin( + "{{directory}}/{{name}}", + { + "directory": target_directory, + "name": concern.parameters.name, + } + ), + } + ) + ); + commands_add( + lib_plankton.string.coin( + "tar --create --directory={{path}} . > {{target_path}}", + { + "path": concern.parameters.path, + "target_path": lib_plankton.string.coin( + "{{directory}}/{{name}}/data.tar", + { + "directory": target_directory, + "name": concern.parameters.name, + } + ), + } + ) + ); + break; + } + case "postgresql_dump": { + const password_file_path: string = "${HOME}/.pgpass"; + commands_add( + lib_plankton.string.coin( + "echo '{{host}}:{{port}}:{{schema}}:{{username}}:{{password}}' > {{path}} && chmod 0600 {{path}}", + { + "path": password_file_path, + "host": concern.parameters.credentials.host, + "port": concern.parameters.credentials.port.toFixed(0), + "username": concern.parameters.credentials.username, + "password": concern.parameters.credentials.password, + "schema": concern.parameters.credentials.schema, + } + ) + ); + commands_add( + lib_plankton.string.coin( + "mkdir --parents {{directory}}", + { + "directory": lib_plankton.string.coin( + "{{directory}}/{{name}}", + { + "directory": target_directory, + "name": concern.parameters.name, + } + ), + } + ) + ); + commands_add( + lib_plankton.string.coin( + "pg_dump --host={{host}} --port={{port}} --username={{username}} {{schema}} > {{target_path}}", + { + "host": concern.parameters.credentials.host, + "port": concern.parameters.credentials.port.toFixed(0), + "username": concern.parameters.credentials.username, + "schema": concern.parameters.credentials.schema, + "target_path": lib_plankton.string.coin( + "{{directory}}/{{name}}/data.sql", + { + "directory": target_directory, + "name": concern.parameters.name, + } + ), + } + ) + ); + commands_add( + lib_plankton.string.coin( + "rm {{path}}", + { + "path": password_file_path, + } + ) + ); + break; + } + default: { + throw (new Error("unhandled kind: " + concern.kind)); + break; + } + } + commands_add( + "" + ); + } + } + commands_add( + lib_plankton.string.coin( + "echo '{{directory}}'", + { + "directory": target_directory, + } + ) + ); + commands_apply(); + break; + } + default: { + throw (new Error("unhandled target kind: " + conf.target.kind)); + break; } } - commands_add( - lib_plankton.string.coin( - "echo '{{directory}}'", - { - "directory": target_directory, - } - ) - ); - commands_apply(); return Promise.resolve(undefined); } diff --git a/tools/update-plankton b/tools/update-plankton index 3fabec2..30591b4 100755 --- a/tools/update-plankton +++ b/tools/update-plankton @@ -6,6 +6,7 @@ dir=lib/plankton modules="" modules="${modules} base" +modules="${modules} conf" modules="${modules} file" modules="${modules} call" modules="${modules} json"