From e73424e2f246b508d7b51ed66fd07c32f8aeb0f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Fra=C3=9F?= Date: Mon, 22 Apr 2024 10:02:43 +0200 Subject: [PATCH] [ini] --- .editorconfig | 27 + .gitignore | 3 + lib/plankton/plankton.d.ts | 2298 +++++++++++ lib/plankton/plankton.js | 6303 +++++++++++++++++++++++++++++++ readme.md | 0 source/logic/backend.ts | 323 ++ source/logic/conf.ts | 43 + source/logic/main.ts | 105 + source/logic/pages/create.ts | 72 + source/logic/pages/index.ts | 5 + source/logic/pages/login.ts | 62 + source/logic/pages/logout.ts | 8 + source/logic/pages/members.ts | 219 ++ source/logic/pages/register.ts | 132 + source/structure/index.html.tpl | 62 + source/style/style.css | 183 + tools/build | 5 + tools/makefile | 49 + tools/run | 5 + tools/update-plankton | 26 + 20 files changed, 9930 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 lib/plankton/plankton.d.ts create mode 100644 lib/plankton/plankton.js create mode 100644 readme.md create mode 100644 source/logic/backend.ts create mode 100644 source/logic/conf.ts create mode 100644 source/logic/main.ts create mode 100644 source/logic/pages/create.ts create mode 100644 source/logic/pages/index.ts create mode 100644 source/logic/pages/login.ts create mode 100644 source/logic/pages/logout.ts create mode 100644 source/logic/pages/members.ts create mode 100644 source/logic/pages/register.ts create mode 100644 source/structure/index.html.tpl create mode 100644 source/style/style.css create mode 100755 tools/build create mode 100644 tools/makefile create mode 100755 tools/run create mode 100755 tools/update-plankton diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..e82584a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,27 @@ +# see https://EditorConfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = tab +indent_style = tab +tab_width = 4 +insert_final_newline = true +max_line_length = 80 +trim_trailing_whitespace = true +curly_bracket_next_line = false +indent_brace_style = K&R +spaces_around_operators = true +spaces_around_brackets = false +quote_type = double + +[*.y{,a}ml{,lint}] +indent_style = space +indent_size = 2 + +[*.md] +indent_style = space +indent_size = 2 + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..17d4b12 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/.geany +/temp/ +/build/ diff --git a/lib/plankton/plankton.d.ts b/lib/plankton/plankton.d.ts new file mode 100644 index 0000000..48a85aa --- /dev/null +++ b/lib/plankton/plankton.d.ts @@ -0,0 +1,2298 @@ +/** + * @author fenris + */ +declare type int = number; +/** + * @author fenris + */ +declare type float = number; +/** + * @author fenris + */ +declare type type_date = { + year: int; + month: int; + day: int; +}; +/** + * @author fenris + */ +declare type type_time = { + hour: int; + minute: int; + second: int; +}; +/** + * @author fenris + */ +declare type type_datetimeobject = { + date: type_date; + time: type_time; +}; +declare class Buffer { + constructor(x: string, modifier?: string); + toString(modifier?: string): string; +} +declare namespace lib_plankton.base { + /** + * @author fenris + */ + function environment(): string; +} +/** + * @author fenris + */ +declare type type_pseudopointer = { + value: type_value; +}; +/** + * @author fenris + */ +declare function pseudopointer_null(): type_pseudopointer; +/** + * @author fenris + */ +declare function pseudopointer_make(value: type_value): type_pseudopointer; +/** + * @author fenris + */ +declare function pseudopointer_isset(pseudopointer: type_pseudopointer): boolean; +/** + * @author fenris + */ +declare function pseudopointer_read(pseudopointer: type_pseudopointer): type_value; +/** + * @author fenris + */ +declare function pseudopointer_write(pseudopointer: type_pseudopointer, value: type_value): void; +/** + * @author fenris + */ +declare var instance_verbosity: int; +/** + * @desc the ability to check for equality with another element of the same domain + * @author fenris + */ +interface interface_collatable { + /** + * @author fenris + */ + _collate(value: type_value): boolean; +} +/** + * @author fenris + */ +declare function instance_collate(value1: (type_value & { + _collate?: ((value: type_value) => boolean); +}), value2: type_value): boolean; +/** + * @desc the ability to compare with another element of the same domain for determining if the first is "smaller than or equal to" the latter + * @author fenris + */ +interface interface_comparable { + /** + * @author fenris + */ + _compare(value: type_value): boolean; +} +/** + * @author fenris + */ +declare function instance_compare(value1: (type_value & { + _compare: ((value: type_value) => boolean); +}), value2: type_value): boolean; +/** + * @desc the ability to create an exact copy + * @author fenris + */ +interface interface_cloneable { + /** + * @author fenris + */ + _clone(): type_value; +} +/** + * @author fenris + */ +declare function instance_clone(value: (type_value & { + _clone?: (() => type_value); +})): type_value; +/** + * @author fenris + */ +interface interface_hashable { + /** + * @author fenris + */ + _hash(): string; +} +/** + * @desc the ability to generate a string out of the element, which identifies it to a high degree + * @author fenris + */ +declare function instance_hash(value: (type_value & { + _hash?: (() => string); +})): string; +/** + * @author fenris + */ +interface interface_showable { + /** + * @author fenris + */ + _show(): string; +} +/** + * @desc the ability to map the element to a textual representation (most likely not injective) + * @author fenris + */ +declare function instance_show(value: (type_value & { + _show?: (() => string); +})): string; +/** + * @author frac + */ +interface interface_decorator { + /** + * @author frac + */ + core: type_core; +} +/** + * @author frac + */ +declare class class_observer { + /** + * @author frac + */ + protected counter: int; + /** + * @author frac + */ + protected actions: { + [id: string]: (information: Object) => void; + }; + /** + * @author frac + */ + protected buffer: Array; + /** + * @author frac + */ + constructor(); + /** + * @author frac + */ + empty(): boolean; + /** + * @author frac + */ + flush(): void; + /** + * @author frac + */ + set(id: string, action: (information: Object) => void): void; + /** + * @author frac + */ + del(id: string): void; + /** + * @author frac + */ + add(action: (information: Object) => void): void; + /** + * @author frac + */ + notify(information?: Object, delayed?: boolean): void; + /** + * @author frac + */ + rollout(): void; +} +/** + * @author frac + */ +/** + * @author frac + */ +/** + * @author frac + */ +declare class class_error extends Error { + /** + * @author frac + */ + protected suberrors: Array; + /** + * @author frac + */ + protected mess: string; + /** + * @author frac + */ + constructor(message: string, suberrors?: Array); + /** + * @override + * @author frac + */ + toString(): string; +} +declare namespace lib_plankton.base { + /** + * returns the current UNIX timestamp + * + * @author fenris + */ + function get_current_timestamp(rounded?: boolean): float; + /** + */ + function object_merge(core: Record, mantle: Record): Record; +} +declare module lib_plankton.pod { + /** + * @author fenris + */ + type type_pod = { + kind: ("empty" | "filled"); + value?: type_value; + }; + /** + * @author fenris + */ + function make_empty(): type_pod; + /** + * @author fenris + */ + function make_filled(value: type_value): type_pod; + /** + * whether the pod is filled + * + * @author fenris + */ + function is_filled(pod: type_pod): boolean; + /** + * return the value, stored in the pod-wrapper + * + * @author fenris + */ + function cull(pod: type_pod): type_value; + /** + * to pass on a empty-pod or to use a filled-pod + * + * @author fenris + */ + function propagate(pod: type_pod, function_: ((value: type_value) => type_value_)): type_pod; + /** + * @author fenris + */ + function distinguish(pod: type_pod, function_empty: (() => type_result), function_filled: ((value: type_value) => type_result)): type_result; + /** + */ + function show(pod: type_pod, options?: { + show_value?: ((value: type_value) => string); + }): string; +} +declare module lib_plankton.pod { + /** + */ + class class_pod { + private subject; + private constructor(); + is_empty(): boolean; + is_filled(): boolean; + cull(): type_value; + show(show_value?: any): string; + toString(): string; + propagate(function_: ((value: type_value) => type_value_)): class_pod; + distinguish(function_empty: (() => type_result), function_filled: ((value: type_value) => type_result)): type_result; + } +} +/** + * might be completely obsolete + */ +declare namespace lib_plankton.call { + /** + * @author fenris + */ + type type_promise = Promise; + /** + * @author fenris + */ + function promise_reject(reason: type_reason): type_promise; + /** + * @author fenris + */ + function promise_resolve(result: type_result): type_promise; + /** + * @author fenris + */ + function promise_make(executor: (resolve: ((result?: type_result) => void), reject: ((reason?: type_reason) => void)) => void): type_promise; + /** + * @author fenris + */ + function promise_then_close(promise: type_promise, resolver: ((result: type_result) => void), rejector: ((reason: type_reason) => void)): void; + /** + * @author fenris + */ + function promise_then_append(promise: type_promise, resolver: ((result: type_result) => type_promise), rejector?: ((reason: type_reason) => type_promise)): type_promise; + /** + * @author fenris + */ + function promise_all(promises: Array>): type_promise, type_reason>; + /** + * @author fenris + */ + function promise_chain(promises: (Array<(input: type_result) => type_promise>), start?: type_result): type_promise; + /** + * @author fenris + */ + function promise_condense(promises: Array<() => type_promise>): type_promise, type_reason>; + /** + * @author fenris + */ + function promise_group(promises: Record type_promise)>, options?: { + serial?: boolean; + }): type_promise, type_reason>; + /** + * @author fenris + */ + function promise_wrap(promise: type_promise, transformator_result: ((reason: type_result_inner) => type_result_outer), transformator_reason?: ((reason: type_reason) => type_reason)): type_promise; + /** + * @author fenris + */ + /** + * @author fenris + */ + /** + * @author fenris + */ + function promise_attach(state: Record, promise: type_promise, name: string): type_promise, type_reason>; + /** + * @author fenris + */ + function promise_delay(promise: type_promise, delay: int): type_promise; +} +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 read(path: string): Promise; + /** + * @author fenris + */ + function write(path: string, content: string): Promise; + /** + * @author fenris + */ + function blob_read_text(blob: Blob): lib_plankton.call.type_promise; + /** + * @author fenris + */ + function blob_read_arraybuffer(blob: Blob): lib_plankton.call.type_promise; + /** + * @author fenris + */ + function blob_read_dataurl(blob: Blob): lib_plankton.call.type_promise; + /** + * @author fenris + */ + function blob_write_text(text: string): lib_plankton.call.type_promise; +} +declare namespace lib_plankton.code { + /** + * @author fenris + */ + interface interface_code { + /** + * @author fenris + */ + encode(x: type_from): type_to; + /** + * @author fenris + */ + decode(x: type_to): type_from; + } +} +declare namespace lib_plankton.code { + /** + * @author fenris + */ + type type_code = { + /** + * @author fenris + */ + encode: (x: type_from) => type_to; + /** + * @author fenris + */ + decode: (x: type_to) => type_from; + }; +} +declare namespace lib_plankton.code { + /** + * @author fenris + */ + function inverse_encode(decode: (to: type_to) => type_from, to: type_to): type_from; + /** + * @author fenris + */ + function inverse_decode(encode: (from: type_from) => type_to, from: type_from): type_to; +} +declare namespace lib_plankton.code { + /** + * @author fenris + */ + class class_code_inverse implements interface_code { + /** + * @author fenris + */ + protected subject: interface_code; + /** + * @author fenris + */ + constructor(subject: interface_code); + /** + * @implementation + * @author fenris + */ + encode(to: type_to): type_from; + /** + * @implementation + * @author fenris + */ + decode(from: type_from): type_to; + } +} +declare namespace lib_plankton.code { + /** + * @author fenris + */ + function pair_encode(encode_first: (from: type_from) => type_between, encode_second: (between: type_between) => type_to, from: type_from): type_to; + /** + * @author fenris + */ + function pair_decode(decode_first: (between: type_between) => type_from, decode_second: (to: type_to) => type_between, to: type_to): type_from; +} +declare namespace lib_plankton.code { + /** + * @author fenris + */ + class class_code_pair implements interface_code { + /** + * @author fenris + */ + protected first: interface_code; + /** + * @author fenris + */ + protected second: interface_code; + /** + * @author fenris + */ + constructor(first: interface_code, second: interface_code); + /** + * @implementation + * @author fenris + */ + encode(from: type_from): type_to; + /** + * @implementation + * @author fenris + */ + decode(to: type_to): type_from; + } +} +declare namespace lib_plankton.code { + /** + * @author fenris + */ + function chain_encode(encode_links: Array<(from: any) => any>, from: any): any; + /** + * @author fenris + */ + function chain_decode(decode_links: Array<(to: any) => any>, to: any): any; +} +declare namespace lib_plankton.code { + /** + * @author fenris + */ + class class_code_chain implements interface_code { + /** + * @author fenris + */ + protected links: Array>; + /** + * @author fenris + */ + constructor(links: Array>); + /** + * @implementation + * @author fenris + */ + encode(from: any): any; + /** + * @implementation + * @author fenris + */ + decode(to: any): any; + } +} +declare namespace lib_plankton.code { + /** + * @author Christian Fraß + */ + type type_flatten_from = Array<{ + [name: string]: any; + }>; + /** + * @author Christian Fraß + */ + type type_flatten_to = { + keys: Array; + data: Array>; + }; + /** + * @author Christian Fraß + */ + function flatten_encode(from: type_flatten_from, keys?: Array): type_flatten_to; + /** + * @author Christian Fraß + */ + function flatten_decode(to: type_flatten_to): type_flatten_from; +} +declare namespace lib_plankton.code { + /** + * @author fenris + */ + class class_code_flatten implements interface_code { + /** + * @author fenris + */ + constructor(); + /** + * @implementation + * @author fenris + */ + encode(x: type_flatten_from): type_flatten_to; + /** + * @implementation + * @author fenris + */ + decode(x: type_flatten_to): type_flatten_from; + } +} +declare namespace lib_plankton.json { + /** + * @author fenris + */ + function encode(x: any, formatted?: boolean): string; + /** + * @author fenris + */ + function decode(x: string): any; +} +declare namespace lib_plankton.json { + /** + * @author fenris + */ + class class_json implements lib_plankton.code.interface_code { + /** + * @author fenris + */ + constructor(); + /** + * @implementation + * @author fenris + */ + encode(x: any): string; + /** + * @implementation + * @author fenris + */ + decode(x: string): any; + } +} +declare namespace lib_plankton.base64 { + /** + * @author fenris + */ + function encode(x: string): string; + /** + * @author fenris + */ + function decode(x: string): string; +} +declare namespace lib_plankton.base64 { + /** + * @author fenris + */ + class class_base64 implements lib_plankton.code.interface_code { + /** + * @author fenris + */ + constructor(); + /** + * @implementation + * @author fenris + */ + encode(x: string): string; + /** + * @implementation + * @author fenris + */ + decode(x: string): string; + } +} +declare namespace lib_plankton.log { + /** + */ + enum enum_level { + debug = 0, + info = 1, + notice = 2, + warning = 3, + error = 4 + } + /** + */ + function level_order(level1: enum_level, level2: enum_level): boolean; + /** + */ + function level_show(level: enum_level): string; + /** + */ + type type_entry = { + level: enum_level; + incident: string; + details: Record; + }; +} +/** + * @deprecated + * @todo remove + */ +declare namespace lib_plankton.log { + function level_push(level: int): void; + function level_pop(): void; + function indent_push(indent: int): void; + function indent_pop(): void; + function indent_inc(): void; + function indent_dec(): void; + /** + * @author fenris + */ + function write({ "message": message, "type": type, "prefix": prefix, "level": level, "indent": indent, }: { + message?: string; + type?: string; + prefix?: string; + level?: int; + indent?: int; + }): void; +} +declare namespace lib_plankton.log { + /** + */ + abstract class class_channel { + /** + */ + abstract add(entry: type_entry): void; + } +} +declare namespace lib_plankton.log { + /** + * output for writing log entries to web console + */ + class class_channel_console extends class_channel { + /** + */ + add(entry: type_entry): void; + } +} +declare namespace lib_plankton.log { + /** + * decorator for filtering out log entries below a certain level threshold + */ + class class_channel_minlevel extends class_channel { + /** + */ + private core; + /** + */ + private threshold; + /** + */ + constructor(core: class_channel, threshold: enum_level); + /** + */ + add(entry: type_entry): void; + } +} +declare namespace lib_plankton.log { + /** + */ + function channel_make(description: { + kind: string; + data?: { + [key: string]: any; + }; + }): class_channel; + /** + */ + type type_configuration = Array; + /** + */ + function conf_default(): type_configuration; +} +declare namespace lib_plankton.log { + /** + * pushes a new configuration on the stack and activates it + */ + function conf_push(channels: type_configuration): void; + /** + * pops the current active configuration from the stack + */ + function conf_pop(): void; + /** + * consumes a log entry, i.e. sends it to the currently active outputs + */ + function add(entry: type_entry): void; + /** + */ + function debug(incident: string, details?: Record): void; + /** + */ + function info(incident: string, details?: Record): void; + /** + */ + function notice(incident: string, details?: Record): void; + /** + */ + function warning(incident: string, details?: Record): void; + /** + */ + function error(incident: string, details?: Record): void; +} +declare var plain_text_to_html: (text: string) => string; +/** + * @desc makes a valid + */ +declare var format_sentence: (str: string, rtl?: boolean, caseSense?: boolean) => string; +declare var fill_string_template: (template_string: string, object: any, fabric: Function, delimiter: string, default_string: string, sloppy: boolean) => string; +declare var make_string_template: (_template: string, _fabrics?: Object) => (object: { + [key: string]: string; +}) => string; +declare var make_eml_header: (object: { + [key: string]: string; +}) => string; +declare var make_eml_body: Object; +declare namespace lib_plankton.string { + /** + * @author neuc,frac + */ + function empty(str: string): boolean; + /** + * @desc returns a unique string + * @param {string} prefix an optional prefix for the generated string + * @return {string} + * @author fenris + */ + function generate(prefix?: string): string; + /** + * @author fenris + */ + function join(parts: Array, glue?: string): string; + /** + * @desc splits a string, but returns an empty list, if the string is empty + * @param {string} chain + * @param {string} separator + * @return {Array} + * @author fenris + */ + function split(chain: string, separator?: string): Array; + /** + * @author neu3no + */ + function explode(str: string, needle: string, max: int): Array; + /** + * @desc concats a given word with itself n times + * @param {string} word + * @param {int} + * @return {string} + * @author fenris + */ + function repeat(word: string, count: int): string; + /** + * @desc lengthens a string by repeatedly appending or prepending another string + * @param {string} word the string to pad + * @param {int} length the length, which the result shall have + * @param {string} symbol the string, which will be added (multiple times) + * @param {boolean} [prepend]; whether to prepend (~true) or append (~false); default: false + * @return {string} the padded string + * @author fenris + */ + function pad(word: string, length: int, symbol?: string, mode?: string): string; + /** + * @desc checks if a given string conttains a certain substring + * @param {string} string + * @param {string} part + * @return {boolean} + * @author fenris + */ + function contains(chain: string, part: string): boolean; + /** + * @desc checks if a given string starts with a certain substring + * @param {string} string + * @param {string} part + * @return {boolean} + * @author fenris + */ + function startsWith(chain: string, part: string): boolean; + /** + * @desc checks if a given string ends with a certain substring + * @param {string} string + * @param {string} part + * @return {boolean} + * @author fenris + */ + function endsWith(chain: string, part: string): boolean; + /** + * @desc count the occourrences of a string in a string + * @param string haystack_string the string wich should be examined + * @param string needle_string the string which should be counted + * @author neuc + */ + function count_occourrences(haystack_string: string, needle_string: string, check_escape: boolean): int; + /** + * @author fenris + */ + function replace(str: string, replacements: Array<{ + from: string; + to: string; + }>, options?: {}): string; + /** + * @desc replaces occurences of "{{name}}" in a string by the corresponding values of an argument object + * @author fenris + */ + function coin(str: string, args: { + [id: string]: string; + }, options?: { + legacy?: boolean; + open?: string; + close?: string; + }): string; + /** + * @author fenris + * @deprecated use limit + */ + function cut(str: string, length: int, delimiter?: string): string; + /** + */ + function limit(str: string, options?: { + length?: int; + indicator?: string; + }): string; + /** + */ + function slice(str: string, size: int): Array; +} +/** + * @deprecated + */ +declare namespace lib_string { + const empty: typeof lib_plankton.string.empty; + const generate: typeof lib_plankton.string.generate; + const split: typeof lib_plankton.string.split; + const explode: typeof lib_plankton.string.repeat; + const repeat: typeof lib_plankton.string.repeat; + const pad: typeof lib_plankton.string.pad; + const contains: typeof lib_plankton.string.contains; + const startsWith: typeof lib_plankton.string.startsWith; + const endsWith: typeof lib_plankton.string.endsWith; + const count_occourrences: typeof lib_plankton.string.count_occourrences; + const coin: typeof lib_plankton.string.coin; + const stance: typeof lib_plankton.string.coin; + const cut: typeof lib_plankton.string.cut; +} +declare namespace lib_plankton.string { + /** + * an implementation of c sprintf + * @param {string} string format string + * @param {array} args arguments which should be filled into + * @returns {string} + */ + var sprintf: (input: string, args?: Array, original?: any) => string; + /** + * an implementation of c printf + * @param {string} string format string + * @param {array} args arguments which should be filled into + * @returns {string} + */ + function printf(format: any, args: any): void; +} +declare var sprintf: (input: string, args?: Array, original?: any) => string; +declare var printf: typeof lib_plankton.string.printf; +declare var eml_log: any; +declare var track_exports: any; +declare var make_logger: (prefix: any, current_loglevel: any) => (obj: any, lvl: any) => void; +declare namespace lib_plankton.database { + /** + */ + type type_query = { + template: string; + arguments: Record; + }; + /** + */ + enum enum_type { + boolean = "boolean", + integer = "integer", + string_short = "string_short", + string_medium = "string_medium", + string_long = "string_long", + float = "float" + } + /** + */ + type type_description_create_table = { + name: string; + key_field?: (null | { + name: string; + type?: enum_type; + comment?: (null | string); + auto_increment?: (null | boolean); + description?: (null | string); + }); + data_fields?: Array<{ + name: string; + nullable?: boolean; + type: enum_type; + default?: any; + description?: (null | string); + }>; + constraints?: Array<{ + kind: string; + parameters?: Record; + }>; + description?: (null | string); + }; + /** + */ + type type_description_insert = { + table_name: string; + values: Record; + }; + /** + */ + type type_description_update = { + table_name: string; + values: Record; + condition?: (null | string); + arguments?: (null | Record); + }; + /** + */ + type type_description_delete = { + table_name: string; + condition?: (null | string); + arguments?: (null | Record); + }; + /** + */ + type type_description_select = { + source: string; + fields?: (null | Array); + condition?: (null | string); + group_by?: (null | string); + having?: (null | string); + order_by?: (null | string); + limit?: (null | int); + arguments?: (null | Record); + }; + /** + * rows + */ + type type_result_get = Array>; + /** + * auto insert id + */ + type type_result_put = (null | int); + /** + * number of affected rows + */ + type type_result_set = int; + /** + * @author fenris + */ + type type_database = { + query_free_get: ((query: type_query) => Promise); + query_free_put: ((query: type_query) => Promise); + query_free_set: ((query: type_query) => Promise); + query_create_table: ((description_create_table: type_description_create_table) => Promise); + query_insert: ((description_insert: type_description_insert) => Promise); + query_update: ((description_update: type_description_update) => Promise); + query_delete: ((description_delete: type_description_delete) => Promise); + query_select: ((description_select: type_description_select) => Promise); + }; + /** + */ + type interface_database = database.type_database; +} +declare namespace lib_plankton.storage { + /** + * implements the idea of a database, which houses datasets (type_value) and manages their access by ids or sth. similar (type_key) + * + * @author fenris + */ + type type_store = { + /** + * shall prepare the storage instance for use + * + * @author fenris + */ + setup(input: type_setup_input): Promise; + /** + * shall insert a new dataset and return its automatically assign key + * + * @author fenris + */ + create(value: type_value): Promise; + /** + * shall modify an existing dataset + * + * @author fenris + */ + update(key: type_key, value: type_value): Promise; + /** + * shall remove an existing dataset + * + * @author fenris + */ + delete(key: type_key): Promise; + /** + * shall get an existing dataset by its key + * + * @author fenris + */ + read(key: type_key): Promise; + /** + * shall list keys and previews of existing datasets, which match a certain search term + * + * @author fenris + */ + search(term?: (null | type_searchterm)): Promise>; + }; + /** + * for class wrappers + */ + type interface_store = type_store; +} +declare namespace lib_plankton.storage { + /** + * implements the idea of a storage without managed keys + * + * @author fenris + */ + type type_chest = { + /** + * shall prepare the storage instance for use + * + * @author fenris + */ + setup(input: type_setup_input): Promise; + /** + * shall remove all items + */ + clear(): Promise; + /** + * shall insert a new or modify an existing dataset and return whether it is new + * + * @author fenris + */ + write(key: type_key, value: type_value): Promise; + /** + * shall remove an existing dataset + * + * @author fenris + */ + delete(key: type_key): Promise; + /** + * shall get an existing dataset by its key + * + * @author fenris + */ + read(key: type_key): Promise; + /** + * shall list keys and previews of existing datasets, which match a certain search term + * + * @author fenris + */ + search(term?: (null | type_searchterm)): Promise>; + }; + /** + * for class wrappers + */ + type interface_chest = type_chest; +} +declare namespace lib_plankton.storage.memory { + /** + * @author fenris + */ + type type_subject = { + data: Record; + }; + /** + */ + type type_parameters = {}; + /** + * @author fenris + */ + function make(parameters: type_parameters): type_subject; + /** + * @author fenris + */ + function clear(subject: type_subject): void; + /** + * @author fenris + */ + function write(subject: type_subject, key: string, value: type_value): boolean; + /** + * @author fenris + */ + function delete_(subject: type_subject, key: string): void; + /** + * @author fenris + */ + function read(subject: type_subject, key: string): type_value; + /** + * @author fenris + */ + function list(subject: type_subject): Array; + /** + * @author fenris + */ + function search(subject: type_subject, term: (null | string)): Array<{ + key: string; + preview: string; + }>; + /** + * @author fenris + */ + function implementation_chest(parameters: type_parameters): type_chest; +} +declare namespace lib_plankton.storage.memory { + /** + * @author fenris + */ + class class_chest implements type_chest { + private subject; + constructor(parameters: type_parameters); + setup(input: any): Promise; + clear(): Promise; + write(key: any, value: any): Promise; + delete(key: any): Promise; + read(key: any): Promise; + search(term: any): Promise<{ + key: string; + preview: string; + }[]>; + } +} +declare namespace lib_plankton.storage.localstorage { + /** + * @author fenris + */ + type type_subject = { + corner: string; + }; + /** + * @author fenris + */ + type type_parameters = { + corner?: string; + }; + /** + * @author fenris + */ + function make(parameters: type_parameters): type_subject; + /** + * @author fenris + */ + function clear(subject: type_subject): void; + /** + * @author fenris + */ + function write(subject: type_subject, key: string, item: string): boolean; + /** + * @author fenris + */ + function delete_(subject: type_subject, key: string): void; + /** + * @author fenris + */ + function read(subject: type_subject, key: string): string; + /** + * @author fenris + */ + function list(subject: type_subject): Array; + /** + */ + function implementation_chest(parameters: type_parameters): type_chest; +} +declare namespace lib_plankton.storage.localstorage { + /** + * uses the browsers localstorage as chest + * + * @author fenris + */ + class class_chest implements type_chest { + private subject; + constructor(parameters: type_parameters); + setup(input: any): Promise; + clear(): Promise; + write(key: any, value: any): Promise; + delete(key: any): Promise; + read(key: any): Promise; + search(term: any): Promise<{ + key: string; + preview: string; + }[]>; + } +} +declare namespace lib_plankton.zoo_input { + /** + * @author fenris + */ + interface interface_input { + /** + */ + setup(parent: HTMLElement): Promise; + /** + */ + read(): Promise; + /** + */ + write(value: type_value): Promise; + } +} +declare namespace lib_plankton.zoo_input { + /** + * @author fenris + */ + class class_input_wrapped implements interface_input { + /** + */ + private core; + /** + */ + private wrap; + /** + */ + private unwrap; + /** + */ + constructor(core: interface_input, wrap: ((value_inner: type_value_inner) => type_value_outer), unwrap: ((value_outer: type_value_outer) => type_value_inner), options?: {}); + /** + * [implementation] + */ + setup(parent: HTMLElement): Promise; + /** + * [implementation] + */ + read(): Promise; + /** + * [implementation] + */ + write(value: type_value_outer): Promise; + } +} +declare namespace lib_plankton.zoo_input { + /** + * @author fenris + */ + class class_input_hidden implements interface_input { + /** + */ + private dom_input; + /** + */ + private value; + /** + */ + constructor(options?: { + initial_value?: any; + }); + /** + * [implementation] + */ + setup(parent: HTMLElement): Promise; + /** + * [implementation] + */ + read(): Promise; + /** + * [implementation] + */ + write(value: any): Promise; + } +} +declare namespace lib_plankton.zoo_input { + /** + * @author fenris + * @todo abstract + */ + class class_input_text implements interface_input { + /** + */ + private read_only; + /** + */ + private pattern; + /** + */ + /** + */ + private dom_input; + /** + */ + constructor(options?: { + read_only?: boolean; + pattern?: (null | string); + }); + /** + * [implementation] + */ + setup(parent: HTMLElement): Promise; + /** + * [implementation] + */ + read(): Promise; + /** + * [implementation] + */ + write(value: string): Promise; + } +} +declare namespace lib_plankton.zoo_input { + /** + * @author fenris + */ + class class_input_email implements interface_input { + /** + */ + private dom_input; + /** + */ + constructor(); + /** + * [implementation] + */ + setup(parent: HTMLElement): Promise; + /** + * [implementation] + */ + read(): Promise; + /** + * [implementation] + */ + write(value: string): Promise; + } +} +declare namespace lib_plankton.zoo_input { + /** + * @author fenris + */ + class class_input_textarea implements interface_input { + /** + */ + private dom_textarea; + /** + */ + constructor(); + /** + * [implementation] + */ + setup(parent: HTMLElement): Promise; + /** + * [implementation] + */ + read(): Promise; + /** + * [implementation] + */ + write(value: string): Promise; + } +} +declare namespace lib_plankton.zoo_input { + /** + * @author fenris + */ + class class_input_date implements interface_input<(null | type_date)> { + /** + */ + private required; + /** + */ + private dom_input; + /** + */ + constructor(options?: { + required?: boolean; + }); + /** + * [implementation] + */ + setup(parent: HTMLElement): Promise; + /** + * [implementation] + */ + read(): Promise<(null | type_date)>; + /** + * [implementation] + */ + write(value: (null | type_date)): Promise; + } +} +declare namespace lib_plankton.zoo_input { + /** + * @author fenris + * @todo abstract + */ + class class_input_number implements interface_input { + /** + */ + private read_only; + /** + */ + private step; + /** + */ + private dom_input; + /** + */ + constructor(options?: { + read_only?: boolean; + step?: (null | float); + }); + /** + * [implementation] + */ + setup(parent: HTMLElement): Promise; + /** + * [implementation] + */ + read(): Promise; + /** + * [implementation] + */ + write(value: number): Promise; + } +} +declare namespace lib_plankton.zoo_input { + /** + * @author fenris + */ + class class_input_checkbox implements interface_input { + /** + */ + private dom_input; + /** + */ + constructor(); + /** + * [implementation] + */ + setup(parent: HTMLElement): Promise; + /** + * [implementation] + */ + read(): Promise; + /** + * [implementation] + */ + write(value: boolean): Promise; + } +} +declare namespace lib_plankton.zoo_input { + /** + * @author fenris + */ + class class_input_selection implements interface_input { + /** + */ + private options; + /** + */ + private dom_select; + /** + */ + constructor(options: Array<{ + value: string; + label: string; + }>); + /** + * [implementation] + */ + setup(parent: HTMLElement): Promise; + /** + * [implementation] + */ + read(): Promise; + /** + * [implementation] + */ + write(value: string): Promise; + } +} +declare namespace lib_plankton.zoo_input { + /** + * @author fenris + */ + class class_input_enumeration implements interface_input { + /** + */ + private options; + /** + */ + private dom_inputs; + /** + */ + constructor(options: Array<{ + value: string; + label: string; + }>); + /** + * [implementation] + * @todo unique name + */ + setup(parent: HTMLElement): Promise; + /** + * [implementation] + */ + read(): Promise; + /** + * [implementation] + */ + write(value: string): Promise; + } +} +declare namespace lib_plankton.zoo_input { + /** + */ + type type_translations = { + add?: string; + remove?: string; + }; + /** + * @author fenris + */ + export class class_input_list implements interface_input> { + /** + */ + private element_input_factory; + /** + */ + private elements_container_dom; + /** + */ + private elements; + /** + */ + private translations; + /** + */ + constructor(element_input_factory: (() => interface_input), options?: { + translations?: type_translations; + }); + /** + */ + private clear; + /** + */ + private add; + /** + * [implementation] + */ + setup(parent: HTMLElement): Promise; + /** + * [implementation] + */ + read(): Promise>; + /** + * [implementation] + */ + write(value: Array): Promise; + } + export {}; +} +declare namespace lib_plankton.zoo_input { + /** + * @author fenris + */ + class class_input_password implements interface_input { + /** + */ + private dom_input; + /** + */ + constructor(); + /** + * [implementation] + */ + setup(parent: HTMLElement): Promise; + /** + * [implementation] + */ + read(): Promise; + /** + * [implementation] + */ + write(value: string): Promise; + } +} +declare namespace lib_plankton.zoo_input { + /** + * @author fenris + */ + class class_input_switch implements interface_input { + /** + */ + private dom_element; + /** + */ + private value; + /** + */ + constructor(); + /** + * [implementation] + */ + setup(parent: HTMLElement): Promise; + /** + * [implementation] + */ + read(): Promise; + /** + * [implementation] + */ + write(value: boolean): Promise; + } +} +declare namespace lib_plankton.zoo_input { + /** + * @author fenris + */ + class class_input_time implements interface_input<(null | type_time)> { + /** + */ + private dom_input; + /** + */ + constructor(); + /** + * [implementation] + */ + setup(parent: HTMLElement): Promise; + /** + * [implementation] + */ + read(): Promise<(null | type_time)>; + /** + * [implementation] + */ + write(value: (null | type_time)): Promise; + } +} +declare namespace lib_plankton.zoo_input { + /** + * @author fenris + */ + class class_input_group implements interface_input { + /** + */ + private fields; + /** + */ + constructor(fields_raw: Array<{ + name: string; + input: interface_input; + label?: (null | string); + help?: (null | string); + }>); + /** + * [implementation] + */ + setup(parent: HTMLElement): Promise; + /** + * [implementation] + */ + read(): Promise; + /** + * [implementation] + */ + write(value: type_record): Promise; + } +} +declare namespace lib_plankton.zoo_form { + /** + */ + type type_field = { + name: string; + type: string; + label: (null | string); + }; + /** + */ + export type type_form = { + method: string; + fields: Array; + encode: ((value: type_value) => Record); + decode: ((raw: Record) => type_value); + class_prefix: string; + root_element: (null | Element); + }; + /** + */ + export function make(method: string, fields: Array<{ + name: string; + type: string; + label?: (null | string); + }>, encode: ((value: type_value) => Record), decode: ((raw: Record) => type_value), options?: { + class_prefix?: string; + }): type_form; + /** + */ + export function make_simple(method: string, fields: Array<{ + name: string; + type: string; + label?: (null | string); + }>, options?: { + class_prefix?: string; + }): type_form>; + /** + */ + export function clear(subject: type_form): void; + /** + */ + export function write(subject: type_form, value: type_value): void; + /** + */ + export function read(subject: type_form): type_value; + /** + */ + export function render(subject: type_form, target: Element): Promise; + export {}; +} +declare namespace lib_plankton.zoo_form { + /** + */ + type type_action = { + label: string; + target?: string; + procedure?: ((get_value?: (() => Promise), get_representation?: (() => Promise)) => void); + }; + /** + * @author fenris + */ + export class class_form { + /** + */ + private encode; + /** + */ + private decode; + /** + */ + private actions; + /** + */ + private input; + /** + */ + constructor(encode: ((value: type_value) => type_representation), decode: ((representation: type_representation) => type_value), input: lib_plankton.zoo_input.interface_input, actions: Array>); + /** + */ + setup(parent: HTMLElement): Promise; + /** + */ + input_read_raw(): Promise; + /** + */ + input_read(): Promise; + /** + */ + input_write(value: type_value): Promise; + } + export {}; +} +declare namespace lib_plankton.zoo_search { + /** + */ + type type_state = { + term: (null | string); + }; + /** + */ + type type_search = { + routine: ((term: string) => Promise>); + encode_item: ((item: type_item) => string); + hooks_select: Array<((item: type_item) => void)>; + hooks_begin: Array<((term?: string) => void)>; + hooks_end: Array<(() => void)>; + class_prefix: string; + root_element: (null | Element); + state: (null | type_state); + }; + /** + */ + function make(routine: ((term: string) => Promise>), options: { + encode_item?: ((item: type_item) => string); + hooks_select?: Array<((item: type_item) => void)>; + hooks_begin?: Array<((term?: string) => void)>; + hooks_end?: Array<(() => void)>; + class_prefix?: string; + }): type_search; + /** + */ + function hook_begin(subject: type_search, action: ((term: string) => void)): void; + /** + */ + function hook_end(subject: type_search, action: (() => void)): void; + /** + */ + function hook_select(subject: type_search, action: ((item: type_item) => void)): void; + /** + */ + function set_state(subject: type_search, state: type_state): Promise; + /** + */ + function render(subject: type_search, target: Element, options?: { + state?: type_state; + }): Promise; +} +declare namespace lib_plankton.zoo_editor { + /** + */ + enum enum_mode { + find = "find", + view = "view", + make = "make" + } + /** + */ + enum enum_action { + keep = "keep", + save = "save", + delete = "delete", + find = "find", + make = "make" + } + /** + */ + enum enum_function { + seek = "seek", + read = "read", + create = "create", + update = "update", + delete = "delete" + } + /** + */ + type type_state = { + mode: enum_mode; + key: (null | type_key); + search_state: lib_plankton.zoo_search.type_state; + }; + /** + */ + type type_editor = { + functions: Array; + store: lib_plankton.storage.type_store; + search: lib_plankton.zoo_search.type_search<{ + key: type_key; + preview: any; + }>; + form: lib_plankton.zoo_form.type_form; + hook_switch: (null | ((state: type_state) => void)); + state: (null | type_state); + class_prefix: string; + root_element: (null | Element); + }; + /** + */ + function make(store: lib_plankton.storage.type_store, form: lib_plankton.zoo_form.type_form, options?: { + functions?: Array; + encode_hit?: ((hit: { + key: type_key; + preview: any; + }) => string); + hook_switch?: (null | ((state: type_state) => void)); + class_prefix?: string; + }): type_editor; + /** + */ + function render(subject: type_editor, target: Element, options?: { + state?: type_state; + }): Promise; +} +declare namespace lib_plankton.zoo_page { + /** + */ + export type type_location = { + name: string; + parameters: Record; + }; + /** + */ + type type_handler = ((parameters: Record, target_element: Element) => void); + /** + */ + export let _pool: Record; + /** + */ + export function encode(location: type_location): string; + /** + */ + export function add_nav_entry(location: type_location, options?: { + label?: (null | string); + }): void; + /** + * encodes a location in the URL and loads it + */ + export function set(location: type_location): void; + /** + */ + export function register(location_name: string, handler: type_handler, options?: {}): void; + /** + */ + export function init(target_element: Element, options?: { + pool?: Record; + fallback?: (null | type_location); + }): void; + /** + */ + export function start(): void; + export {}; +} diff --git a/lib/plankton/plankton.js b/lib/plankton/plankton.js new file mode 100644 index 0000000..060ea8c --- /dev/null +++ b/lib/plankton/plankton.js @@ -0,0 +1,6303 @@ +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +/* +This file is part of »bacterio-plankton:base«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:base« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:base« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:base«. If not, see . + */ +// } +/* +This file is part of »bacterio-plankton:base«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:base« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:base« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:base«. If not, see . + */ +; +/* +declare class console { + static log(...args : any[]) : void; + static info(...args : any[]) : void; + static warn(...args : any[]) : void; + static error(...args : any[]) : void; +}; + */ +var lib_plankton; +(function (lib_plankton) { + var base; + (function (base) { + /** + * @author fenris + */ + function environment() { + return "web"; + } + base.environment = environment; + })(base = lib_plankton.base || (lib_plankton.base = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:base«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:base« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:base« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:base«. If not, see . + */ +/** + * @author fenris + */ +/*export*/ function pseudopointer_null() { + return { + "value": null + }; +} +/** + * @author fenris + */ +/*export*/ function pseudopointer_make(value) { + return { + "value": value + }; +} +/** + * @author fenris + */ +/*export*/ function pseudopointer_isset(pseudopointer) { + return (pseudopointer.value != null); +} +/** + * @author fenris + */ +/*export*/ function pseudopointer_read(pseudopointer) { + if (pseudopointer.value != null) { + return pseudopointer.value; + } + else { + var message = "nullpointer dereferencation"; + throw (new Error(message)); + } +} +/** + * @author fenris + */ +/*export*/ function pseudopointer_write(pseudopointer, value) { + pseudopointer.value = value; +} +/* +This file is part of »bacterio-plankton:base«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:base« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:base« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:base«. If not, see . + */ +/** + * @author fenris + */ +var instance_verbosity = 0; +/** + * @author fenris + */ +function instance_collate(value1, value2) { + if (typeof (value1) === "object") { + if (value1 == null) { + return (value2 == null); + } + else { + if ("_collate" in value1) { + return value1["_collate"](value2); + } + else { + throw (new Error("[collate]" + " " + "object has no such method")); + } + } + } + else { + if (instance_verbosity >= 1) { + // lib_plankton.log.warn("[collate]" + " " + "primitive value; using default implementation"); + } + return (value1 === value2); + } +} +/** + * @author fenris + */ +function instance_compare(value1, value2) { + if (typeof (value1) === "object") { + if ("_compare" in value1) { + return value1["_compare"](value2); + } + else { + throw (new Error("[compare]" + " " + "object has no such method")); + } + } + else { + if (instance_verbosity >= 1) { + // lib_plankton.log.warn("[compare]" + " " + "primitive value; using default implementation"); + } + return (value1 <= value2); + } +} +/** + * @author fenris + */ +function instance_clone(value) { + if (typeof (value) === "object") { + if ("_clone" in value) { + return value["_clone"](); + } + else { + throw (new Error("[clone]" + " " + "object has no such method")); + } + } + else { + if (instance_verbosity >= 1) { + // lib_plankton.log.warn("[clone]" + " " + "primitive value; using default implementation"); + } + return value; + } +} +/** + * @desc the ability to generate a string out of the element, which identifies it to a high degree + * @author fenris + */ +function instance_hash(value) { + if (typeof (value) === "object") { + if ("_hash" in value) { + return value["_hash"](); + } + else { + throw (new Error("[hash]" + " " + "object has no such method")); + } + } + else { + if (instance_verbosity >= 1) { + // lib_plankton.log.warn("[hash]" + " " + "primitive value; using default implementation"); + } + return String(value); + } +} +/** + * @desc the ability to map the element to a textual representation (most likely not injective) + * @author fenris + */ +function instance_show(value) { + if (typeof (value) === "object") { + if (value == null) { + return "NULL"; + } + else { + if ("_show" in value) { + return value["_show"](); + } + else { + // throw (new Error("[show]" + " " + "object has no such method")); + return JSON.stringify(value); + } + } + } + else { + if (instance_verbosity >= 1) { + // lib_plankton.log.warn("[show]" + " " + "primitive value; using default implementation"); + } + return String(value); + } +} +/* +This file is part of »bacterio-plankton:base«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:base« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:base« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:base«. If not, see . + */ +/** + * @author frac + */ +var class_observer = /** @class */ (function () { + /** + * @author frac + */ + function class_observer() { + this.counter = 0; + this.actions = {}; + this.buffer = []; + } + /** + * @author frac + */ + class_observer.prototype.empty = function () { + return (Object.keys(this.actions).length == 0); + }; + /** + * @author frac + */ + class_observer.prototype.flush = function () { + this.actions = {}; + }; + /** + * @author frac + */ + class_observer.prototype.set = function (id, action) { + this.actions[id] = action; + }; + /** + * @author frac + */ + class_observer.prototype.del = function (id) { + delete this.actions[id]; + }; + /** + * @author frac + */ + class_observer.prototype.add = function (action) { + this.set((this.counter++).toString(), action); + }; + /** + * @author frac + */ + class_observer.prototype.notify = function (information, delayed) { + var _this = this; + if (information === void 0) { information = {}; } + if (delayed === void 0) { delayed = false; } + if (delayed) { + this.buffer.push(information); + } + else { + Object.keys(this.actions).forEach(function (id) { return _this.actions[id](information); }); + } + }; + /** + * @author frac + */ + class_observer.prototype.rollout = function () { + var _this = this; + this.buffer.forEach(function (information) { return _this.notify(information, false); }); + this.buffer = []; + }; + return class_observer; +}()); +/** + * @author frac + */ +/* +export interface interface_readable { + + |** + * @author frac + *| + read() : type_executor; + +} + */ +/** + * @author frac + */ +/* +export interface interface_writeable { + + |** + * @author frac + *| + write(value : type_value) : type_executor; + +} + */ +/* +This file is part of »bacterio-plankton:base«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:base« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:base« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:base«. If not, see . + */ +/** + * @author frac + */ +var class_error = /** @class */ (function (_super) { + __extends(class_error, _super); + /** + * @author frac + */ + function class_error(message, suberrors) { + if (suberrors === void 0) { suberrors = []; } + var _this = _super.call(this, message) || this; + _this.suberrors = suberrors; + _this.mess = message; + return _this; + } + /** + * @override + * @author frac + */ + class_error.prototype.toString = function () { + return ( /*super.toString()*/this.mess + " " + ("[" + this.suberrors.map(function (x) { return x.toString(); }).join(",") + "]")); + }; + return class_error; +}(Error)); +var lib_plankton; +(function (lib_plankton) { + var base; + (function (base) { + /** + * returns the current UNIX timestamp + * + * @author fenris + */ + function get_current_timestamp(rounded) { + if (rounded === void 0) { rounded = false; } + var x = (Date.now() / 1000); + return (rounded ? Math.round(x) : x); + ; + } + base.get_current_timestamp = get_current_timestamp; + /** + */ + function object_merge(core, mantle) { + return Object.assign(core, mantle); + } + base.object_merge = object_merge; + })(base = lib_plankton.base || (lib_plankton.base = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:pod«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:pod« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:pod« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:pod«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var pod; + (function (pod_1) { + /** + * @author fenris + */ + function make_empty() { + return { + "kind": "empty" + }; + } + pod_1.make_empty = make_empty; + /** + * @author fenris + */ + function make_filled(value) { + return { + "kind": "filled", + "value": value + }; + } + pod_1.make_filled = make_filled; + /** + * whether the pod is filled + * + * @author fenris + */ + function is_filled(pod) { + return (pod.kind === "filled"); + } + pod_1.is_filled = is_filled; + /** + * return the value, stored in the pod-wrapper + * + * @author fenris + */ + function cull(pod) { + if (!is_filled(pod)) { + throw (new Error("cull from empty")); + } + else { + return pod.value; + } + } + pod_1.cull = cull; + /** + * to pass on a empty-pod or to use a filled-pod + * + * @author fenris + */ + function propagate(pod, function_) { + if (!is_filled(pod)) { + return make_empty(); + } + else { + return make_filled(function_(pod.value)); + } + } + pod_1.propagate = propagate; + /** + * @author fenris + */ + function distinguish(pod, function_empty, function_filled) { + return ((!is_filled(pod)) + ? function_empty() + : function_filled(pod.value)); + } + pod_1.distinguish = distinguish; + /** + */ + function show(pod, options = {}) { + options = Object.assign({ + "show_value": value => String(value), + }, options); + if (!is_filled(pod)) { + return "<·>"; + } + else { + return ("<- " + options.show_value(pod.value) + " ->"); + } + } + pod_1.show = show; + })(pod = lib_plankton.pod || (lib_plankton.pod = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:pod«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:pod« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:pod« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:pod«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var pod; + (function (pod) { + /** + */ + class class_pod { + constructor(subject) { this.subject = subject; } + is_empty() { return (!pod.is_filled(this.subject)); } + is_filled() { return pod.is_filled(this.subject); } + cull() { return pod.cull(this.subject); } + show(show_value = undefined) { return pod.show(this.subject, show_value); } + toString() { return this.show(); } + propagate(function_) { return new class_pod(pod.propagate(this.subject, function_)); } + distinguish(function_empty, function_filled) { return pod.distinguish(this.subject, function_empty, function_filled); } + } + pod.class_pod = class_pod; + })(pod = lib_plankton.pod || (lib_plankton.pod = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:call«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:call« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:call« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:call«. If not, see . + */ +/** + * might be completely obsolete + */ +var lib_plankton; +(function (lib_plankton) { + var call; + (function (call) { + /** + * @author fenris + */ + function promise_reject(reason) { + return Promise.reject(reason); + } + call.promise_reject = promise_reject; + /** + * @author fenris + */ + function promise_resolve(result) { + return Promise.resolve(result); + } + call.promise_resolve = promise_resolve; + /** + * @author fenris + */ + function promise_make(executor) { + return (new Promise(executor)); + } + call.promise_make = promise_make; + /** + * @author fenris + */ + function promise_then_close(promise, resolver, rejector) { + promise.then(resolver, rejector); + } + call.promise_then_close = promise_then_close; + /** + * @author fenris + */ + function promise_then_append(promise, resolver, rejector = null) { + if (rejector == null) { + rejector = (reason) => promise_reject(reason); + } + return (promise.then(resolver, rejector)); + } + call.promise_then_append = promise_then_append; + /** + * @author fenris + */ + function promise_all(promises) { + return Promise.all(promises); + } + call.promise_all = promise_all; + /** + * @author fenris + */ + function promise_chain(promises, start = undefined) { + return (promises.reduce((chain, promise) => promise_then_append(chain, promise), promise_resolve(start))); + } + call.promise_chain = promise_chain; + /** + * @author fenris + */ + function promise_condense(promises) { + return (promise_chain(promises.map(promise => result => promise_then_append(promise(), element => promise_resolve(result.concat([element])))), [])); + } + call.promise_condense = promise_condense; + /** + * @author fenris + */ + function promise_group(promises, options = { + "serial": false, + }) { + const decorate = function (promise, name) { + return (() => promise_then_append(promise(), value => promise_resolve({ "key": name, "value": value }))); + }; + if (options.serial) { + return (promise_then_append(promise_condense(Object.keys(promises) + .map(name => decorate(promises[name], name))), list => promise_resolve(Object.fromEntries(list.map(({ "key": key, "value": value }) => ([key, value])))))); + } + else { + return (promise_then_append(promise_all(Object.keys(promises) + .map(name => decorate(promises[name], name)) + .map(promise => promise())), list => promise_resolve(Object.fromEntries(list.map(({ "key": key, "value": value }) => ([key, value])))))); + } + } + call.promise_group = promise_group; + /** + * @author fenris + */ + function promise_wrap(promise, transformator_result, transformator_reason = lib_plankton.call.id) { + return (promise_make((resolve, reject) => { + promise_then_close(promise, result => resolve(transformator_result(result)), reason => reject(transformator_reason(reason))); + })); + } + call.promise_wrap = promise_wrap; + /** + * @author fenris + */ + /* + export function promise_show(label : string) : (result : type_result)=>type_promise { + return ( + result => promise_make( + (resolve, reject) => { + // lib_plankton.log.info(label + ": " + instance_show(result)); + process.stdout.write(label + ": " + instance_show(result)); + resolve(result); + } + ) + ); + } + */ + /** + * @author fenris + */ + /* + export function promise_log(result : type_result) : (result : type_result)=>type_promise { + return promise_show("log"); + } + */ + /** + * @author fenris + */ + function promise_attach(state, promise, name) { + return (promise_wrap(promise, result => { + state[name] = result; + return state; + })); + } + call.promise_attach = promise_attach; + /** + * @author fenris + */ + function promise_delay(promise, delay) { + return promise_make((resolve, reject) => { + call.timeout(() => { + promise_then_close(promise, resolve, reject); + return null; + }, delay); + }); + } + call.promise_delay = promise_delay; + })(call = lib_plankton.call || (lib_plankton.call = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:call«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:call« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:call« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:call«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var call; + (function (call) { + /** + */ + class CancellablePromise extends Promise { + /** + */ + constructor(executor) { + super((resolve, reject) => { }); + this.subject = (new Promise((resolve, reject) => { + Promise.race([ + new Promise(executor), + new Promise((resolve_, reject_) => { + this.interval = setInterval(() => { + if (!this.cancelled) { + // do nothing + } + else { + reject_(new Error("cancelled")); + this.clear(); + } + }, 0); + }), + ]) + .then(resolve, reject); + })); + this.cancelled = false; + this.interval = null; + } + /** + */ + clear() { + if (this.interval === null) { + // do nothing + } + else { + clearInterval(this.interval); + this.interval = null; + } + } + /** + */ + then(onfulfilled, onrejected) { + this.clear(); + return this.subject.then(onfulfilled, onrejected); + } + /** + */ + catch(x) { + this.clear(); + return this.subject.catch(x); + } + /** + */ + cancel() { + this.cancelled = true; + this.clear(); + } + } + call.CancellablePromise = CancellablePromise; + })(call = lib_plankton.call || (lib_plankton.call = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:call«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:call« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:call« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:call«. If not, see . + */ +/** + * initializer might be obsolete, since promises are reusable after having been resolved or rejected + */ +var lib_plankton; +(function (lib_plankton) { + var call; + (function (call) { + /** + * @author fenris + */ + let enum_initializer_state; + (function (enum_initializer_state) { + enum_initializer_state[enum_initializer_state["initial"] = 0] = "initial"; + enum_initializer_state[enum_initializer_state["waiting"] = 1] = "waiting"; + enum_initializer_state[enum_initializer_state["successful"] = 2] = "successful"; + enum_initializer_state[enum_initializer_state["failed"] = 3] = "failed"; + })(enum_initializer_state = call.enum_initializer_state || (call.enum_initializer_state = {})); + /** + * @author fenris + */ + function initializer_make(fetcher) { + let subject = { + "fetcher": fetcher, + "state": enum_initializer_state.initial, + "queue": [], + "result": undefined, + "reason": undefined, + }; + return subject; + } + call.initializer_make = initializer_make; + /** + * @author fenris + */ + function initializer_actuate(subject) { + switch (subject.state) { + case enum_initializer_state.successful: { + subject.queue.forEach(entry => entry.resolve(subject.result)); + break; + } + case enum_initializer_state.failed: { + subject.queue.forEach(entry => entry.reject(subject.reason)); + break; + } + default: { + throw (new Error(`unhandled state ${subject.state}`)); + break; + } + } + } + /** + * @author fenris + */ + function initializer_reset(subject) { + subject.state = enum_initializer_state.initial; + subject.queue = []; + } + call.initializer_reset = initializer_reset; + /** + * @author fenris + */ + function initializer_state(subject) { + return subject.state; + } + call.initializer_state = initializer_state; + /** + * @author fenris + */ + function initializer_get(subject) { + switch (subject.state) { + case enum_initializer_state.initial: { + subject.state = enum_initializer_state.waiting; + return (call.promise_make((resolve, reject) => { + subject.queue.push({ "resolve": resolve, "reject": reject }); + subject.fetcher().then(result => { + subject.state = enum_initializer_state.successful; + subject.result = result; + initializer_actuate(subject); + }, reason => { + subject.state = enum_initializer_state.failed; + subject.reason = reason; + initializer_actuate(subject); + }); + })); + break; + } + case enum_initializer_state.waiting: { + return (call.promise_make((resolve, reject) => { + subject.queue.push({ "resolve": resolve, "reject": reject }); + })); + break; + } + case enum_initializer_state.successful: { + return (call.promise_resolve(subject.result)); + break; + } + case enum_initializer_state.failed: { + return (call.promise_reject(subject.reason)); + break; + } + default: { + throw (new Error(`unhandled state ${subject.state}`)); + break; + } + } + } + call.initializer_get = initializer_get; + /** + * @author fenris + */ + function initializer_get_sync(subject) { + switch (subject.state) { + case enum_initializer_state.successful: { + return subject.result; + break; + } + case enum_initializer_state.failed: { + throw subject.reason; + break; + } + default: { + throw (new Error(`unhandled state ${subject.state}`)); + break; + } + } + } + /** + * @author fenris + */ + function initializer_set_sync(subject, result) { + switch (subject.state) { + case enum_initializer_state.successful: { + subject.result = result; + break; + } + case enum_initializer_state.failed: { + subject.state = enum_initializer_state.successful; + subject.result = result; + break; + } + default: { + throw (new Error(`unhandled state ${subject.state}`)); + break; + } + } + } + })(call = lib_plankton.call || (lib_plankton.call = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:call«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:call« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:call« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:call«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var call; + (function (call) { + /* + The core idea of this library is to provide means for asynchronous program flow. The old-school way to do is, + is to use callbacks. While this approach is simple and easy to understand, it has some disadvantages. As an + attempt to relief and improve this, the promise-system was introduced. In principle it solves most of the + problems found in the callback-approach; however it has some downsides as well: + + - Convolution of multiple principles + Promises unite the ideas of asynchronous program flow and error handling. + + - Instant execution + Creating a promise results in the instant execution of the given executor prodecure. While this might be + convenient in some cases, it can be quite disturbing and counter-intuitive in others. + + - Broken typing + The Promise system doesn't distinguish between an appending "then" (i.e. passing a function, which returns a + new promise) and a closing "then" (i.e. passing a function, which has no return value). On top of that it + allows returning simple values in an appending "then", which results in an implicit call of the executors + "resolve"-function. The price for these "pragmatic" features is that the whole system can't be typed well. + And even though JavaScript is not a strictly typed language, it was a quite questionable decision to design + the promise system in a way, which breaks typing from the start. + + The deferral-system forseeks to solve these issues while retaining the advantages of the promise-system. + */ + /** + * @author fenris + * @desc activates the deferral and handles its output according to a given procedure + * @param {(value : type_value)=>void} procedure a function which receives the output of the deferral as argument + */ + function deferral_use(deferral, input, procedure) { + deferral.representation(input).then(value => { + procedure(value); + }, reason => { + throw reason; + }); + } + call.deferral_use = deferral_use; + /** + * @author fenris + * @desc creates a deferral-subject (similar to "new Promise", where "convey" reflects "resolve"/"reject") + */ + function deferral_make(handler) { + return ({ + "representation": ((input) => (new Promise((resolve, reject) => { + handler(input, resolve); + }))) + }); + } + call.deferral_make = deferral_make; + /** + * @author fenris + * @desc wraps a simple function into a deferral (similar to "Promise.resolve"/"Promise.reject") + */ + function deferral_wrap(function_) { + return (deferral_make((input, convey) => convey(function_(input)))); + } + call.deferral_wrap = deferral_wrap; + /** + * @author fenris + */ + function deferral_id() { + return (deferral_make((input, convey) => convey(input))); + } + call.deferral_id = deferral_id; + /** + * @author fenris + */ + function deferral_const(value) { + return (deferral_make((input, convey) => convey(value))); + } + call.deferral_const = deferral_const; + /** + * @author fenris + */ + function deferral_delay(output, delay) { + return (deferral_make((input, convey) => { + setTimeout(() => convey(output), delay); + })); + } + call.deferral_delay = deferral_delay; + /** + * @author fenris + * @desc connects two deferrals to form a new one; the output of the first is taken as input for the second + * (similar to "Promise.then" when passing a function which returns a new promise) + * @param {type_deferral} first a simple deferral + * @param {(value1 : type_value1)=>type_deferral} second a function depending from a value returning a deferral + */ + function deferral_compose_serial(first, second) { + return { + "representation": ((input) => first.representation(input).then((between) => second.representation(between))) + }; + } + call.deferral_compose_serial = deferral_compose_serial; + /** + * @author fenris + */ + function deferral_compose_parallel({ "left": deferral_left, "right": deferral_right, }) { + return (deferral_make((input, convey) => { + let object = { + "left": lib_plankton.pod.make_empty(), + "right": lib_plankton.pod.make_empty(), + }; + let finish = function () { + if (lib_plankton.pod.is_filled(object.left) + && + lib_plankton.pod.is_filled(object.right)) { + let result = { + "left": lib_plankton.pod.cull(object.left), + "right": lib_plankton.pod.cull(object.right), + }; + convey(result); + } + else { + // do nothing + } + }; + deferral_use(deferral_left, input, output_left => { + object.left = lib_plankton.pod.make_filled(output_left); + finish(); + }); + deferral_use(deferral_right, input, output_right => { + object.right = lib_plankton.pod.make_filled(output_right); + finish(); + }); + })); + } + call.deferral_compose_parallel = deferral_compose_parallel; + /** + * @author fenris + * @desc repeatedly applied serial composition + */ + function deferral_chain(members) { + return (members.reduce( + // (result, current) => deferral_compose_serial(result, current), + deferral_compose_serial, deferral_id())); + } + call.deferral_chain = deferral_chain; + /** + * @author fenris + */ + /* + export function deferral_bunch( + members : {[name : string] : type_deferral} + ) : type_deferral { + + } + */ + })(call = lib_plankton.call || (lib_plankton.call = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:call«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:call« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:call« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:call«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var call; + (function (call) { + /** + * @author fenris + */ + class class_deferral { + /** + * @author fenris + */ + constructor(subject) { + this.subject = subject; + } + /** + * @author fenris + */ + static _cram(subject) { + return (new class_deferral(subject)); + } + /** + * @author fenris + */ + static _tear(instance) { + return instance.subject; + } + /** + * @author fenris + */ + static make(handler) { + return (class_deferral._cram(call.deferral_make(handler))); + } + /** + * @author fenris + */ + use(input, procedure) { + return (call.deferral_use(class_deferral._tear(this), input, procedure)); + } + /** + * @author fenris + */ + compose_serial(second) { + return (class_deferral._cram(call.deferral_compose_serial(class_deferral._tear(this), class_deferral._tear(second)))); + } + /** + * @author fenris + */ + static chain(members) { + return (class_deferral._cram(call.deferral_chain(members.map(member => class_deferral._tear(member))))); + } + /** + * @author fenris + */ + static wrap(function_) { + return (class_deferral._cram(call.deferral_wrap(function_))); + } + /** + * @author fenris + */ + static const_(value) { + return (class_deferral._cram(call.deferral_const(value))); + } + /** + * @author fenris + */ + static delay(output, delay) { + return (class_deferral._cram(call.deferral_delay(output, delay))); + } + } + call.class_deferral = class_deferral; + })(call = lib_plankton.call || (lib_plankton.call = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:call«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:call« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:call« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:call«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var call; + (function (call) { + /** + * converts the "arguments"-map into an array + * + * @param {Object} args + * @author fenris + */ + function args2list(args) { + return Object.keys(args).map(key => args[key]); + } + call.args2list = args2list; + /** + * just the empty function; useful for some callbacks etc. + * + * @author fenris + */ + function nothing() { + } + call.nothing = nothing; + /** + * just the identity; useful for some callbacks etc.; defined as function instead of const for using type parameters + * + * @author fenris + */ + function id(x) { + return x; + } + call.id = id; + /** + * just the identity; useful for some callbacks etc. + * + * @author fenris + */ + function const_(x) { + return (y => x); + } + call.const_ = const_; + /** + * composes two functions (i.e. returns a function that return the result of the successive execution of both input-functions) + * + * @param {function} function_f + * @param {function} function_g + * @author fenris + */ + function compose(function_f, function_g) { + return (function (x) { + // return function_g(function_f(x)); + return function_g(function_f.apply(function_f, args2list(arguments))); + }); + } + call.compose = compose; + /** + * @author fenris + */ + function curryfy_real(f, n) { + switch (n) { + case 0: { + throw (new Error("[curryfy] impossible")); + // break; + } + case 1: { + return f; + // break; + } + default: { + return (function (x) { + return (curryfy_real(function () { return f.apply(f, [x].concat(args2list(arguments))); }, n - 1)); + }); + // break; + } + } + } + /** + * transforms a function with sequential input to a function with leveled input; example: add(2,3) = curryfy(add)(2)(3) + * + * @param {function} f + * @return {function} the currified version of the in put function + * @author fenris + */ + function curryfy(f) { + return curryfy_real(f, f.length); + } + call.curryfy = curryfy; + /** + * @author fenris + */ + function convey(value, functions) { + let result = value; + functions.forEach(function_ => { + result = function_(result); + }); + return result; + } + call.convey = convey; + /** + * @author fenris + */ + function timeout(procedure, delay_in_seconds) { + return ( + /*window.*/ setTimeout(procedure, Math.floor(delay_in_seconds * 1000))); + } + call.timeout = timeout; + /** + * Promise version of "setTimeout" + * + * @author fenris + */ + function defer(seconds, action) { + return (new Promise((resolve, reject) => { + setTimeout(() => resolve(action()), Math.floor(seconds * 1000)); + })); + } + call.defer = defer; + /** + * a definition for a value being "defined" + * + * @author neuc + */ + function is_def(obj, options = {}) { + options = Object.assign({ + "null_is_valid": false, + }, options); + return (!((typeof (obj) === "undefined") + || + (!options.null_is_valid && (obj === null)))); + } + call.is_def = is_def; + /** + * returns the value if set and, when a type is specified, if the type is correct, if not return default_value + * + * @author neuc + */ + function def_val(value, default_value, options = {}) { + options = Object.assign({ + "type": null, + "null_is_valid": false, + }, options); + if (is_def(value, { "null_is_valid": options.null_is_valid }) + && + (is_def(options.type) + ? ((typeof (value) === options.type) + || + ((value === null) + && + options.null_is_valid)) + : true)) { + return value; + } + else { + return default_value; + } + } + call.def_val = def_val; + ; + /** + * provides the call for an attribute of a class as a regular function; useful for processing lists of objects + * + * @param {string} name the name of the attribute + * @return {function} + * @author fenris + */ + function attribute(name) { + return (object => object[name]); + } + call.attribute = attribute; + /** + * provides a method of a class as a regular function; useful for processing lists of objects + * + * @param {string} name the name of the method + * @return {function} + * @author fenris + */ + function method(name) { + return (function (object) { return object[name].apply(object, args2list(arguments).slice(1)); }); + } + call.method = method; + /** + * @author fenris + */ + function distinguish(coproduct, handlers, options = {}) { + options = Object.assign({ + "fallback": null, + }, options); + if (coproduct.kind in handlers) { + const handler = handlers[coproduct.kind]; + return handler(coproduct.data); + } + else { + const message = ("unhandled kind '" + coproduct.kind + "'"); + if (options.fallback !== null) { + console.warn(message); + return options.fallback(coproduct); + } + else { + throw (new Error(message)); + } + } + } + call.distinguish = distinguish; + /** + * 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, + }); + } + 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, + }); + } + } + } + call.rate_limit_check = rate_limit_check; + })(call = lib_plankton.call || (lib_plankton.call = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:file«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:file« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:file« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:file«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var file; + (function (file) { + /** + * @author fenris + */ + function read(path) { + return (fetch("/" + path) + .then(function (result) { return result.text(); })); + } + file.read = read; + /** + * @author fenris + */ + function write(path, content) { + return Promise.reject(new Error("not implemented / not possible")); + } + file.write = write; + /** + * @author fenris + */ + function blob_read_text(blob) { + return (lib_plankton.call.promise_make(function (resolve, reject) { + var reader = (new FileReader()); + reader.addEventListener("load", function (event) { + resolve((reader.result)); + }); + reader.addEventListener("error", function (event) { + reject(new Error("reading file failed")); + }); + reader.addEventListener("abort", function (event) { + reject(new Error("reading file aborted")); + }); + reader.readAsText(blob); + })); + } + file.blob_read_text = blob_read_text; + /** + * @author fenris + */ + function blob_read_arraybuffer(blob) { + return (lib_plankton.call.promise_make(function (resolve, reject) { + var reader = (new FileReader()); + reader.addEventListener("load", function (event) { + resolve((reader.result)); + }); + reader.addEventListener("error", function (event) { + reject(new Error("reading file failed")); + }); + reader.addEventListener("abort", function (event) { + reject(new Error("reading file aborted")); + }); + reader.readAsArrayBuffer(blob); + })); + } + file.blob_read_arraybuffer = blob_read_arraybuffer; + /** + * @author fenris + */ + function blob_read_dataurl(blob) { + return (lib_plankton.call.promise_make(function (resolve, reject) { + var reader = new FileReader(); + reader.addEventListener("load", function (event) { + resolve((reader.result)); + }); + reader.addEventListener("error", function (event) { + reject(new Error("reading file failed")); + }); + reader.addEventListener("abort", function (event) { + reject(new Error("reading file aborted")); + }); + reader.readAsDataURL(blob); + })); + } + file.blob_read_dataurl = blob_read_dataurl; + /** + * @author fenris + */ + function blob_write_text(text) { + var blob = (new Blob([text], { "type": "text/plain" })); + return lib_plankton.call.promise_resolve(blob); + } + file.blob_write_text = blob_write_text; + })(file = lib_plankton.file || (lib_plankton.file = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:code« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:code«. If not, see . + */ +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:code« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:code«. If not, see . + */ +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:code« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:code«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var code; + (function (code) { + /** + * @author fenris + */ + function inverse_encode(decode, to) { + return decode(to); + } + code.inverse_encode = inverse_encode; + /** + * @author fenris + */ + function inverse_decode(encode, from) { + return encode(from); + } + code.inverse_decode = inverse_decode; + })(code = lib_plankton.code || (lib_plankton.code = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:code« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:code«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var code; + (function (code) { + /** + * @author fenris + */ + var class_code_inverse = /** @class */ (function () { + /** + * @author fenris + */ + function class_code_inverse(subject) { + this.subject = subject; + } + /** + * @implementation + * @author fenris + */ + class_code_inverse.prototype.encode = function (to) { + var _this = this; + return code.inverse_encode(function (x) { return _this.subject.decode(x); }, to); + }; + /** + * @implementation + * @author fenris + */ + class_code_inverse.prototype.decode = function (from) { + var _this = this; + return code.inverse_decode(function (x) { return _this.subject.encode(x); }, from); + }; + return class_code_inverse; + }()); + code.class_code_inverse = class_code_inverse; + })(code = lib_plankton.code || (lib_plankton.code = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:code« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:code«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var code; + (function (code) { + /** + * @author fenris + */ + function pair_encode(encode_first, encode_second, from) { + var between = encode_first(from); + var to = encode_second(between); + return to; + } + code.pair_encode = pair_encode; + /** + * @author fenris + */ + function pair_decode(decode_first, decode_second, to) { + var between = decode_second(to); + var from = decode_first(between); + return from; + } + code.pair_decode = pair_decode; + })(code = lib_plankton.code || (lib_plankton.code = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:code« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:code«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var code; + (function (code) { + /** + * @author fenris + */ + var class_code_pair = /** @class */ (function () { + /** + * @author fenris + */ + function class_code_pair(first, second) { + this.first = first; + this.second = second; + } + /** + * @implementation + * @author fenris + */ + class_code_pair.prototype.encode = function (from) { + var _this = this; + return code.pair_encode(function (x) { return _this.first.encode(x); }, function (x) { return _this.second.encode(x); }, from); + }; + /** + * @implementation + * @author fenris + */ + class_code_pair.prototype.decode = function (to) { + var _this = this; + return code.pair_decode(function (x) { return _this.first.decode(x); }, function (x) { return _this.second.decode(x); }, to); + }; + return class_code_pair; + }()); + code.class_code_pair = class_code_pair; + })(code = lib_plankton.code || (lib_plankton.code = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:code« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:code«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var code; + (function (code) { + /** + * @author fenris + */ + function chain_encode(encode_links, from) { + var value = from; + encode_links + .forEach(function (link) { + value = link(value); + }); + return value; + } + code.chain_encode = chain_encode; + /** + * @author fenris + */ + function chain_decode(decode_links, to) { + var value = to; + decode_links + .reverse() + .forEach(function (link) { + value = link(value); + }); + return value; + } + code.chain_decode = chain_decode; + })(code = lib_plankton.code || (lib_plankton.code = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:code« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:code«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var code; + (function (code) { + /** + * @author fenris + */ + var class_code_chain = /** @class */ (function () { + /** + * @author fenris + */ + function class_code_chain(links) { + this.links = links; + } + /** + * @implementation + * @author fenris + */ + class_code_chain.prototype.encode = function (from) { + return code.chain_encode(this.links.map(function (link) { return (function (x) { return link.encode(x); }); }), from); + }; + /** + * @implementation + * @author fenris + */ + class_code_chain.prototype.decode = function (to) { + return code.chain_decode(this.links.map(function (link) { return (function (x) { return link.decode(x); }); }), to); + }; + return class_code_chain; + }()); + code.class_code_chain = class_code_chain; + })(code = lib_plankton.code || (lib_plankton.code = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:code« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:code«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var code; + (function (code) { + /** + * @author Christian Fraß + */ + function flatten_encode(from, keys) { + if (keys === void 0) { keys = null; } + if (keys === null) { + if (from.length > 0) { + keys = Object.keys(from[0]); + } + else { + throw (new Error("encoding impossible")); + } + } + return { + "keys": keys, + "data": from.map(function (line) { return keys.map(function (name) { return line[name]; }); }) + }; + } + code.flatten_encode = flatten_encode; + /** + * @author Christian Fraß + */ + function flatten_decode(to) { + return (to.data + .map(function (dataset) { + var dataset_ = {}; + dataset + .forEach(function (value, index) { + var name = to.keys[index]; + dataset_[name] = value; + }); + return dataset_; + })); + } + code.flatten_decode = flatten_decode; + })(code = lib_plankton.code || (lib_plankton.code = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:code«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:code« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:code« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:code«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var code; + (function (code) { + /** + * @author fenris + */ + var class_code_flatten = /** @class */ (function () { + /** + * @author fenris + */ + function class_code_flatten() { + } + /** + * @implementation + * @author fenris + */ + class_code_flatten.prototype.encode = function (x) { + return code.flatten_encode(x); + }; + /** + * @implementation + * @author fenris + */ + class_code_flatten.prototype.decode = function (x) { + return code.flatten_decode(x); + }; + return class_code_flatten; + }()); + code.class_code_flatten = class_code_flatten; + })(code = lib_plankton.code || (lib_plankton.code = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:json«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:json« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:json« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:json«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var json; + (function (json) { + /** + * @author fenris + */ + function encode(x, formatted = false) { + return JSON.stringify(x, undefined, formatted ? "\t" : undefined); + } + json.encode = encode; + /** + * @author fenris + */ + function decode(x) { + return JSON.parse(x); + } + json.decode = decode; + })(json = lib_plankton.json || (lib_plankton.json = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:json«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:json« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:json« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:json«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var json; + (function (json) { + /** + * @author fenris + */ + class class_json { + /** + * @author fenris + */ + constructor() { + } + /** + * @implementation + * @author fenris + */ + encode(x) { + return json.encode(x); + } + /** + * @implementation + * @author fenris + */ + decode(x) { + return json.decode(x); + } + } + json.class_json = class_json; + })(json = lib_plankton.json || (lib_plankton.json = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:base64«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:base64« 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:base64« 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:base64«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var base64; + (function (base64) { + /** + * @author fenris + */ + function encode(x) { + return btoa(x); + } + base64.encode = encode; + /** + * @author fenris + */ + function decode(x) { + return atob(x); + } + base64.decode = decode; + })(base64 = lib_plankton.base64 || (lib_plankton.base64 = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:base64«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:base64« 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:base64« 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:base64«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var base64; + (function (base64) { + /** + * @author fenris + */ + class class_base64 { + /** + * @author fenris + */ + constructor() { + } + /** + * @implementation + * @author fenris + */ + encode(x) { + return base64.encode(x); + } + /** + * @implementation + * @author fenris + */ + decode(x) { + return base64.decode(x); + } + } + base64.class_base64 = class_base64; + })(base64 = lib_plankton.base64 || (lib_plankton.base64 = {})); +})(lib_plankton || (lib_plankton = {})); +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:log« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:lang« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:log«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var log; + (function (log) { + /** + */ + var enum_level; + (function (enum_level) { + enum_level[enum_level["debug"] = 0] = "debug"; + enum_level[enum_level["info"] = 1] = "info"; + enum_level[enum_level["notice"] = 2] = "notice"; + enum_level[enum_level["warning"] = 3] = "warning"; + enum_level[enum_level["error"] = 4] = "error"; + })(enum_level = log.enum_level || (log.enum_level = {})); + ; + /** + */ + function level_order(level1, level2) { + return (level1 <= level2); + } + log.level_order = level_order; + /** + */ + function level_show(level) { + switch (level) { + case enum_level.debug: return "debug"; + case enum_level.info: return "info"; + case enum_level.notice: return "notice"; + case enum_level.warning: return "warning"; + case enum_level.error: return "error"; + default: return "(unknown)"; + } + } + log.level_show = level_show; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:log« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:lang« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:lang«. If not, see . + */ +/** + * @deprecated + * @todo remove + */ +var lib_plankton; +(function (lib_plankton) { + var log; + (function (log) { + /** + * @author fenris + */ + /*export*/ var level_stack = [0]; + function level_push(level) { level_stack.push(level); } + log.level_push = level_push; + function level_pop() { if (level_stack.length > 1) { + level_stack.pop(); + } } + log.level_pop = level_pop; + function level_get() { return level_stack.slice(-1)[0]; } + /* + export function level_inc() : void {level_push(level_get()+1);} + export function level_dec() : void {level_push(level_get()-1);} + */ + /** + * @author fenris + */ + var indent_stack = [0]; + function indent_push(indent) { indent_stack.push(indent); } + log.indent_push = indent_push; + function indent_pop() { if (indent_stack.length > 1) { + indent_stack.pop(); + } } + log.indent_pop = indent_pop; + function indent_get() { return level_stack.slice(-1)[0]; } + function indent_inc() { level_push(level_get() + 1); } + log.indent_inc = indent_inc; + function indent_dec() { level_push(level_get() - 1); } + log.indent_dec = indent_dec; + /** + * @author fenris + */ + function write(_a) { + var message = _a["message"], _b = _a["type"], type = _b === void 0 ? null : _b, _c = _a["prefix"], prefix = _c === void 0 ? null : _c, _d = _a["level"], level = _d === void 0 ? 0 : _d, _e = _a["indent"], indent = _e === void 0 ? 0 : _e; + var entry = { + "level": ((type === null) + ? lib_plankton.log.enum_level.info + : { + "debug": lib_plankton.log.enum_level.debug, + "info": lib_plankton.log.enum_level.info, + "notice": lib_plankton.log.enum_level.notice, + "warning": lib_plankton.log.enum_level.warning, + "error": lib_plankton.log.enum_level.error + }[type]), + "incident": message, + "details": { + "prefix": prefix, + "level": level, + "indent": indent + } + }; + lib_plankton.log.add(entry); + } + log.write = write; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:log« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:lang« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:log«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var log; + (function (log) { + /** + */ + var class_channel = /** @class */ (function () { + function class_channel() { + } + return class_channel; + }()); + log.class_channel = class_channel; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:log« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:lang« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:log«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var log; + (function (log) { + /** + * output for writing log entries to web console + */ + var class_channel_console = /** @class */ (function (_super) { + __extends(class_channel_console, _super); + function class_channel_console() { + return _super !== null && _super.apply(this, arguments) || this; + } + /** + */ + class_channel_console.prototype.add = function (entry) { + var _a; + var renderers = (_a = {}, + _a[log.enum_level.debug] = { + "renderer": function (i, d) { return console.log(i, d); }, + "show_level": true + }, + _a[log.enum_level.info] = { + "renderer": function (i, d) { return console.info(i, d); }, + "show_level": false + }, + _a[log.enum_level.notice] = { + "renderer": function (i, d) { return console.log(i, d); }, + "show_level": true + }, + _a[log.enum_level.warning] = { + "renderer": function (i, d) { return console.warn(i, d); }, + "show_level": false + }, + _a[log.enum_level.error] = { + "renderer": function (i, d) { return console.error(i, d); }, + "show_level": false + }, + _a); + var setting = renderers[entry.level]; + setting.renderer(((setting.show_level + ? ("[" + log.level_show(entry.level) + "]" + " ") + : "") + + + ("" + entry.incident + "")), entry.details); + }; + return class_channel_console; + }(log.class_channel)); + log.class_channel_console = class_channel_console; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:log« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:lang« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:log«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var log; + (function (log) { + /** + * decorator for filtering out log entries below a certain level threshold + */ + var class_channel_minlevel = /** @class */ (function (_super) { + __extends(class_channel_minlevel, _super); + /** + */ + function class_channel_minlevel(core, threshold) { + var _this = _super.call(this) || this; + _this.core = core; + _this.threshold = threshold; + return _this; + } + /** + */ + class_channel_minlevel.prototype.add = function (entry) { + if (!log.level_order(this.threshold, entry.level)) { + // do nothing + } + else { + this.core.add(entry); + } + }; + return class_channel_minlevel; + }(log.class_channel)); + log.class_channel_minlevel = class_channel_minlevel; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:log« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:lang« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:log«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var log; + (function (log) { + /** + */ + function translate_level(level_string) { + return { + "debug": log.enum_level.debug, + "info": log.enum_level.info, + "notice": log.enum_level.notice, + "warning": log.enum_level.warning, + "error": log.enum_level.error + }[level_string]; + } + /** + */ + function channel_make(description) { + var _a; + switch (description.kind) { + default: { + throw (new Error("unhandled log channel kind: " + description.kind)); + break; + } + case "console": { + return (new log.class_channel_minlevel(new log.class_channel_console(), translate_level((_a = description.data["threshold"]) !== null && _a !== void 0 ? _a : "debug"))); + break; + } + } + } + log.channel_make = channel_make; + /** + */ + function conf_default() { + return [ + new log.class_channel_minlevel(new log.class_channel_console(), log.enum_level.notice), + ]; + } + log.conf_default = conf_default; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:log«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:log« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:lang« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:log«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var log; + (function (log) { + /** + */ + var _channel_stack = null; + /** + * pushes a new configuration on the stack and activates it + */ + function conf_push(channels) { + if (_channel_stack === null) { + _channel_stack = []; + } + _channel_stack.push(channels); + } + log.conf_push = conf_push; + /** + * pops the current active configuration from the stack + */ + function conf_pop() { + if (_channel_stack.length > 0) { + _channel_stack.pop(); + } + else { + // do nothing + } + } + log.conf_pop = conf_pop; + /** + * makes the logging system ready + */ + function setup() { + if (_channel_stack === null) { + _channel_stack = []; + conf_push(log.conf_default()); + } + else { + // do nothing + } + } + /** + * consumes a log entry, i.e. sends it to the currently active outputs + */ + function add(entry) { + setup(); + _channel_stack.slice(-1)[0].forEach(function (channel) { return channel.add(entry); }); + } + log.add = add; + /** + */ + function debug(incident, details) { + if (details === void 0) { details = {}; } + add({ "level": log.enum_level.debug, "incident": incident, "details": details }); + } + log.debug = debug; + /** + */ + function info(incident, details) { + if (details === void 0) { details = {}; } + add({ "level": log.enum_level.info, "incident": incident, "details": details }); + } + log.info = info; + /** + */ + function notice(incident, details) { + if (details === void 0) { details = {}; } + add({ "level": log.enum_level.notice, "incident": incident, "details": details }); + } + log.notice = notice; + /** + */ + function warning(incident, details) { + if (details === void 0) { details = {}; } + add({ "level": log.enum_level.warning, "incident": incident, "details": details }); + } + log.warning = warning; + /** + */ + function error(incident, details) { + if (details === void 0) { details = {}; } + add({ "level": log.enum_level.error, "incident": incident, "details": details }); + } + log.error = error; + })(log = lib_plankton.log || (lib_plankton.log = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:string«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:string« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:string« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:string«. If not, see . + */ +var plain_text_to_html = function (text) { + let ret = text; + ret = ret.replace(/ /g, "  "); // convert multiple whitespace to forced ones + ret = ret.split("\n").join("
"); + return ret; +}; +/** + * @desc makes a valid + */ +var format_sentence = function (str, rtl = false, caseSense = true) { + if (str === "") { + return str; + } + else { + let marks = { + ".": true, + "?": true, + "!": true + }; + let default_mark = "."; + let ret = str.split(""); + if (!rtl) { + ret[0] = ret[0].toLocaleUpperCase(); + if (!(ret[ret.length - 1] in marks)) { + ret.push(default_mark); + } + } + else { + ret[ret.length - 1] = ret[ret.length - 1].toLocaleUpperCase(); + if (!(ret[0] in marks)) { + ret.unshift(default_mark); + } + } + return ret.join(""); + } +}; +var fill_string_template = function (template_string, object, fabric = function (object, key) { return object[key]; }, delimiter = "%", default_string = null, sloppy) { + function get_tags(str) { + let r = new RegExp(delimiter + "[^\\s^" + delimiter + "]+" + delimiter, "gi"); + return ((str.match(r) || []).map(function (e) { + return e.slice(delimiter.length, e.length - delimiter.length); + })); + } + function replace_tag(str, tag, value) { + let r = new RegExp(delimiter + tag + delimiter, "gi"); + return str.replace(r, value); + } + function replace_tags(str, obj) { + return (get_tags(str).reduce(function (ret, key) { + let value = ""; + try { + value = fabric(obj, key); + if ((!sloppy && (value === void 0)) || (sloppy && (value == void 0))) { + value = default_string; + } + } + catch (e) { + console.warn("invalid placeholder " + key); + value = default_string; + } + return replace_tag(ret, key, value); + }, str)); + } + return replace_tags(template_string, object); +}; +var make_string_template = function (_template, _fabrics = {}) { + function replace_tag(str, tag, value) { + var r = new RegExp("%" + tag + "%", "gi"); + return str.replace(r, value); + } + function replace_tags(str, obj) { + return (Object.keys(obj).reduce(function (ret, key) { + return replace_tag(ret, key, _fabrics[key] || obj[key]); + }, str)); + } + return (function (tags) { + return replace_tags(_template, tags); + }); +}; +var make_eml_header = (function () { + let _template = ""; + _template += "From: %from%\n"; + _template += "To: %recipient%\n"; + _template += "Subject: %subject%\n"; + _template += "X-Mailer: greenscale-plankton.emlgen\n"; + return make_string_template(_template); +})(); +var make_eml_body = (function () { + let exports = {}; + exports["simple_body"] = make_string_template("Content-Type: %contenttype%\n\n%body%\n\n"); + // very basic implementation + // parts = [{contenttype:"text/html; charset=UTF-8", body: "

foo

" }, {...}] + exports["body_boundrary"] = function (parts, boundrary) { + let _template = ""; + _template += "--%boundrary%\n"; + _template += "Content-Type: %contenttype%\n\n%body%\n\n"; + //_template += "--%boundrary%--\n\n"; + let maker = make_string_template(_template); + return (parts.reduce(function (prev, curr) { + curr.boundrary = boundrary; + return [prev, maker(curr)].join(""); + }, "")); + }; + // body must be base64 encoded! + exports["attachment_boundrary"] = function (parts, boundrary) { + let _template = ""; + _template += "--%boundrary%\n"; + _template += "Content-Type: %contenttype%\n"; + _template += "Content-Transfer-Encoding: base64\n"; + _template += "Content-Disposition: %disposition%; filename=\"%name%\"\n\n"; + _template += "%body%\n\n"; + //_template += "--%boundrary%--\n\n"; + let maker = make_string_template(_template); + return (parts.reduce(function (prev, curr) { + curr.boundrary = boundrary; + if (curr.disposition === void 0) + curr.disposition = "inline"; + return [prev, maker(curr)].join(""); + }, "")); + }; + exports["gen_boundrary"] = function () { + return ("xxxxxxxxxxxxxxxxxxxxxx".replace(/[xy]/g, function (c) { + let r = crypto.getRandomValues(new Uint8Array(1))[0] % 16 | 0, v = c == "x" ? r : (r & 0x3 | 0x8); + return v.toString(16); + })); + }; + // simple implementation without alternatives (old rfc) + exports["complete_boundrary"] = function (bodyparts, attachments) { + let ret = ""; + let boundrary = exports["gen_boundrary"](); + ret += exports["body_boundrary"](bodyparts, boundrary); + ret += exports["attachment_boundrary"](attachments, boundrary); + ret += "--" + boundrary + "--\n\nINVISIBLE!!!!"; + return (exports["simple_body"]({ + "contenttype": sprintf("multipart/mixed; boundary=%s", [boundrary]), + "body": ret + })); + }; + return exports; +})(); +/* +This file is part of »bacterio-plankton:string«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:string« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:string« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:string«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var string; + (function (string) { + /** + * @author fenris + */ + const hexdigits = 4; + /** + * @author fenris + */ + const index_max = (1 << (4 * hexdigits)); + /** + * @author fenris + */ + var index_is = 0; + /** + * @author neuc,frac + */ + function empty(str) { + return (str.trim() === ""); + } + string.empty = empty; + /** + * @desc returns a unique string + * @param {string} prefix an optional prefix for the generated string + * @return {string} + * @author fenris + */ + function generate(prefix = "string_") { + if (index_is > index_max) { + throw (new Error("[string_generate] out of valid indices")); + } + else { + return string.sprintf(prefix + "%0" + hexdigits.toString() + "X", [index_is++]); + } + } + string.generate = generate; + /** + * @author fenris + */ + function join(parts, glue = " ") { + if (parts.length == 0) { + return ""; + } + else { + return parts.join(glue); + } + } + string.join = join; + /** + * @desc splits a string, but returns an empty list, if the string is empty + * @param {string} chain + * @param {string} separator + * @return {Array} + * @author fenris + */ + function split(chain, separator = " ") { + if (chain.length == 0) { + return []; + } + else { + return chain.split(separator); + } + } + string.split = split; + /** + * @author neu3no + */ + function explode(str, needle, max) { + let temp = str.split(needle); + const right = temp.splice(max - 1); + temp.push(right.join(needle)); + return temp; + } + string.explode = explode; + /** + * @desc concats a given word with itself n times + * @param {string} word + * @param {int} + * @return {string} + * @author fenris + */ + function repeat(word, count) { + // return ((count == 0) ? "" : (word + repeat(word, count-1))); + let result = ""; + for (let n = 0; n < count; n += 1) { + result += word; + } + return result; + } + string.repeat = repeat; + /** + * @desc lengthens a string by repeatedly appending or prepending another string + * @param {string} word the string to pad + * @param {int} length the length, which the result shall have + * @param {string} symbol the string, which will be added (multiple times) + * @param {boolean} [prepend]; whether to prepend (~true) or append (~false); default: false + * @return {string} the padded string + * @author fenris + */ + function pad(word, length, symbol = " ", mode = "append") { + switch (mode) { + case "prepend": { + // insert symbols only at the beginning + while (word.length < length) + word = symbol + word; + return word.substring(word.length - length); + break; + } + case "append": { + // insert symbols only at the end + while (word.length < length) + word = word + symbol; + return word.substring(0, length); + break; + } + case "widen": { + // insert symbols at both sides + let left = (((length - word.length) & 1) === 0); + while (word.length < length) { + word = (left + ? (symbol + word) + : (word + symbol)); + left = (!left); + } + return word.substring(0, length); + break; + } + default: { + const message = ("unhandled mode '" + mode + "'"); + console.warn(message); + return word; + break; + } + } + } + string.pad = pad; + /** + * @desc checks if a given string conttains a certain substring + * @param {string} string + * @param {string} part + * @return {boolean} + * @author fenris + */ + function contains(chain, part) { + if (typeof (chain) !== "string") { + return false; + } + return (chain.indexOf(part) >= 0); + } + string.contains = contains; + /** + * @desc checks if a given string starts with a certain substring + * @param {string} string + * @param {string} part + * @return {boolean} + * @author fenris + */ + function startsWith(chain, part) { + if (typeof (chain) !== "string") { + return false; + } + // return (string.indexOf(part) === 0); + return ((function (m, n) { + if (n === 0) { + return true; + } + else { + if (m === 0) { + return false; + } + else { + return ((chain[0] == part[0]) + && + startsWith(chain.substring(1), part.substring(1))); + } + } + })(chain.length, part.length)); + } + string.startsWith = startsWith; + /** + * @desc checks if a given string ends with a certain substring + * @param {string} string + * @param {string} part + * @return {boolean} + * @author fenris + */ + function endsWith(chain, part) { + if (typeof (chain) !== "string") { + return false; + } + // return (string.lastIndexOf(part) === string.length-part.length); + return ((function (m, n) { + if (n === 0) { + return true; + } + else { + if (m === 0) { + return false; + } + else { + // console.info(("(" + string[m-1] + " == " + part[n-1] + ")") + " = " + String(string[m-1] == part[n-1])); + return ((chain[m - 1] === part[n - 1]) + && + endsWith(chain.substring(0, m - 1), part.substring(0, n - 1))); + } + } + })(chain.length, part.length)); + } + string.endsWith = endsWith; + /** + * @desc count the occourrences of a string in a string + * @param string haystack_string the string wich should be examined + * @param string needle_string the string which should be counted + * @author neuc + */ + function count_occourrences(haystack_string, needle_string, check_escape) { + let cnt = 0; + let pos = -1; + do { + pos = haystack_string.indexOf(needle_string, pos + 1); + if ((!check_escape) || (haystack_string[pos - 1] != "\\")) { + cnt++; + } + } while (pos >= 0); + return (cnt - 1); + } + string.count_occourrences = count_occourrences; + /** + * @author fenris + */ + function replace(str, replacements, options = {}) { + options = Object.assign({}, options); + let result = str; + replacements.forEach(replacement => { + lib_plankton.log.debug("lib_plankton.string.replace", { + "from": replacement.from, + "to": replacement.to, + }); + result = result.replace(new RegExp(replacement.from, "g"), replacement.to); + }); + return result; + } + string.replace = replace; + /** + * @desc replaces occurences of "{{name}}" in a string by the corresponding values of an argument object + * @author fenris + */ + function coin(str, args, options = {}) { + options = Object.assign({ + "legacy": false, + "open": "{{", + "close": "}}", + }, options); + Object.keys(args).forEach((key) => { + // old syntax + { + if (options.legacy) { + const value = args[key]; + const regexp_argument = new RegExp("\\${" + key + "}", "g"); + lib_plankton.log.debug("lib_plankton.string.coin", { + "key": key, + "regex": regexp_argument.toString(), + "value": value, + }); + str = str.replace(regexp_argument, value); + } + } + // new syntax + { + const value = args[key]; + const regexp_argument = new RegExp(options.open + key + options.close, "g"); + lib_plankton.log.debug("lib_plankton.string.coin", { + "key": key, + "regex": regexp_argument.toString(), + "value": value, + }); + str = str.replace(regexp_argument, value); + } + }); + return str; + } + string.coin = coin; + /** + * @author fenris + * @deprecated use limit + */ + function cut(str, length, delimiter = "…") { + if (str.length <= length) { + return str; + } + else { + return (str.slice(0, length - delimiter.length) + delimiter); + } + } + string.cut = cut; + /** + */ + function limit(str, options = {}) { + options = Object.assign({ + "length": 120, + "indicator": "…", + }, options); + return ((str.length <= options.length) + ? str + : (str.slice(0, options.length - options.indicator.length) + options.indicator)); + } + string.limit = limit; + /** + */ + function slice(str, size) { + let slices = []; + let rest = str; + while (rest.length > 0) { + slices.push(rest.slice(0, size)); + rest = rest.slice(size); + } + return slices; + } + string.slice = slice; + })(string = lib_plankton.string || (lib_plankton.string = {})); +})(lib_plankton || (lib_plankton = {})); +/** + * @deprecated + */ +var lib_string; +(function (lib_string) { + lib_string.empty = lib_plankton.string.empty; + lib_string.generate = lib_plankton.string.generate; + lib_string.split = lib_plankton.string.split; + lib_string.explode = lib_plankton.string.repeat; + lib_string.repeat = lib_plankton.string.repeat; + lib_string.pad = lib_plankton.string.pad; + lib_string.contains = lib_plankton.string.contains; + lib_string.startsWith = lib_plankton.string.startsWith; + lib_string.endsWith = lib_plankton.string.endsWith; + lib_string.count_occourrences = lib_plankton.string.count_occourrences; + lib_string.coin = lib_plankton.string.coin; + lib_string.stance = lib_plankton.string.coin; + lib_string.cut = lib_plankton.string.cut; +})(lib_string || (lib_string = {})); +/* +This file is part of »bacterio-plankton:string«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:string« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:string« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:string«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var string; + (function (string) { + var pattern = /%([-+#0 ]*)([0-9]*)[\.]{0,1}([0-9]*)([\w]{1})/; + var gpattern = /%([-+#0 ]*)([0-9]*)[\.]{0,1}([0-9]*)([\w]{1})/g; + function split_format(format) { + var tmp = format.match(pattern); + if (tmp === null) + return null; + return { + 'flags': tmp[1].split(""), + 'width': Number(tmp[2]), + 'precision': tmp[3] === '' ? null : Number(tmp[3]), + 'specifier': tmp[4], + 'string': format + }; + } + function make_err(format, arg, should) { + return ("[sprintf]" + " " + "argument for '" + format.string + "' has to be '" + should + "' but '" + arg + "' is '" + typeof arg + "'!"); + } + function test_arg(format, arg, should) { + if (typeof arg !== should) { + console.warn(make_err(format, arg, should)); + return false; + } + return true; + } + function string_fill(str, char, len, left) { + while (str.length < len) { + if (left) { + str += char; + } + else { + str = char + str; + } + } + return str; + } + /** + * the known_parameters are used to parse the different identifiers for the welln known syntax: + * flag width precision identifier + * %{[0#+- ]}{[0-9]*}.{[0-9]*}[fFdiueEgGsoxXaAsn] + * flags: + * 0 - fill with '0' instead of ' ' if the string length < width + * # - not implemented + * - - left-justified -> fill on the right side to reach width + * + - force using '+' on positive numbers + * ' ' - add a single space before positive numbers + * + * identifiers + * %f, %F - interpret given number as float, width: the minimal total width (fill with ' ' or '0' if the + * resulting string is too short, precision: cut more then given decimal places + * %d, %i, %u - interpret number as integer, decimal places will be cut. width: like float, precision: + * fill with '0' on right side until length given in precision is reached + * %e - interpret as float and write as scientifical number, width & precision like in float + * %E - same es %e but uppercase 'E' + * %g - use the shortest string of %f or %e + * %G - use the shortest string of %E or %E + * %s - simply print a string + * %o - print the given number in octal notation + * %x - print the given number in hex notation + * %X - same as %x but with uppercase characters + * %a - alias to %x + * %A - alias to %X + * %n - just print nothing + * @type {{}} + */ + var known_params = {}; + known_params["f"] = function (format, arg) { + if (!test_arg(format, arg, "number")) + return "Ø"; + var tmp = Math.abs(arg); + var sign = (arg < 0) ? -1 : 1; + var tmp_result = null; + if (format.precision !== null) { + tmp = Math.floor(Math.pow(10, format.precision) * tmp) / Math.pow(10, format.precision); + var tmp_ = (tmp * sign).toString().split("."); + if (tmp_.length === 1) + tmp_.push(""); + tmp_[1] = string_fill(tmp_[1], "0", format.precision, true); + tmp_result = tmp_.join("."); + } + else { + tmp_result = (sign * tmp).toString(); + } + if ((format.flags.indexOf(" ") >= 0) && (arg >= 0)) { + tmp_result = " " + tmp; + } + else if ((format.flags.indexOf("+") >= 0) && (arg >= 0)) { + tmp_result = "+" + tmp; + } + tmp_result = string_fill(tmp, (format.flags.indexOf("0") >= 0) ? "0" : " ", format.width, (format.flags.indexOf("-") >= 0)); + return tmp_result; + }; + known_params["F"] = known_params["f"]; + known_params["d"] = function (format, arg) { + if (!test_arg(format, arg, 'number')) + return 'Ø'; + var tmp = (((arg < 0 && format.specifier !== 'u') ? -1 : 1) * Math.floor(Math.abs(arg))).toString(); + if ((format.specifier === 'd' || format.specifier === 'i') && format.flags.indexOf(' ') >= 0 && arg >= 0) { + tmp = ' ' + tmp; + } + else if ((format.specifier === 'd' || format.specifier === 'i') && format.flags.indexOf('+') >= 0 && arg >= 0) { + tmp = '+' + tmp; + } + tmp = string_fill(tmp, format.flags.indexOf('0') >= 0 ? '0' : ' ', format.width, format.flags.indexOf('-') >= 0); + tmp = string_fill(tmp, '0', format.precision === null ? 0 : format.precision, false); + return tmp; + }; + known_params["i"] = known_params["d"]; + known_params["u"] = known_params["d"]; + known_params["e"] = function (format, arg) { + if (!test_arg(format, arg, 'number')) + return 'Ø'; + var tmp = arg.toExponential(format.precision === null ? undefined : format.precision).toString(); + if (format.flags.indexOf(' ') >= 0 && arg >= 0) { + tmp = ' ' + tmp; + } + else if (format.flags.indexOf('+') >= 0 && arg >= 0) { + tmp = '+' + tmp; + } + tmp = string_fill(tmp, format.flags.indexOf('0') >= 0 ? '0' : ' ', format.width, format.flags.indexOf('-') >= 0); + return tmp; + }; + known_params["E"] = function (format, arg) { + return known_params["e"](format, arg).toUpperCase(); + }; + known_params["g"] = function (format, arg) { + if (!test_arg(format, arg, 'number')) + return 'Ø'; + var tmpf = known_params["f"](format, arg); + var tmpe = known_params["e"](format, arg); + if (tmpf.length < tmpe.length) { + return tmpf; + } + else { + return tmpe; + } + }; + known_params["G"] = function (format, arg) { + return known_params["g"](format, arg).toUpperCase(); + }; + known_params["s"] = function (format, arg) { + if (!test_arg(format, arg, 'string')) + return 'o.O'; + var tmp = format.precision !== null ? arg.substr(0, format.precision) : arg; + tmp = string_fill(tmp, format.flags.indexOf('0') >= 0 ? '0' : ' ', format.width, format.flags.indexOf('-') >= 0); + return tmp; + }; + known_params["o"] = function (format, arg) { + if (!test_arg(format, arg, 'number')) + return 'Ø'; + var tmp = Math.floor(Math.round(Math.abs(arg))) * ((arg < 0) ? -1 : 1); + return known_params["s"](format, tmp.toString(8)); + }; + known_params["x"] = function (format, arg) { + if (!test_arg(format, arg, 'number')) + return 'Ø'; + var tmp = Math.floor(Math.round(Math.abs(arg))) * ((arg < 0) ? -1 : 1); + return known_params["s"](format, tmp.toString(16)); + }; + known_params["a"] = known_params["x"]; + known_params["X"] = function (format, arg) { + if (!test_arg(format, arg, 'number')) + return 'Ø'; + return known_params["x"](format, arg).toUpperCase(); + }; + known_params["A"] = known_params["X"]; + known_params["c"] = function (format, arg) { + var tmp = ""; + if (typeof arg === "number") { + tmp = String.fromCharCode(arg); + } + else if ((typeof arg === "string") && (arg.length === 1)) { + tmp = arg[0]; + } + else { + console.warn(make_err(format, arg, "number|string") + " and if string it needs to have the length of 1!"); + } + return known_params["s"](format, tmp); + }; + known_params["n"] = function () { + return ""; + }; + var decompose = function (chain, regexp) { + var result = regexp.exec(chain); + if (result == null) { + return null; + } + else { + var front = chain.substring(0, result.index); + var back = chain.substring(result.index + result[0].length); + return { "front": front, "match": result[0], "back": back }; + } + }; + /** + * an implementation of c sprintf + * @param {string} string format string + * @param {array} args arguments which should be filled into + * @returns {string} + */ + string.sprintf = function (input, args = [], original = null) { + if (original == null) + original = input; + var components = decompose(input, pattern); + if (components == null) { + if (args.length > 0) { + console.warn("[sprintf] superfluous arguments while formatting '" + original + "': ", args); + } + return input; + } + else { + var arg; + var rest; + if (args.length > 0) { + arg = args[0]; + rest = args.slice(1); + } + else { + console.warn("[sprintf] out of arguments while formatting '" + original + "'"); + arg = null; + rest = []; + return input; + } + var fmt = split_format(components["match"]); + return (components["front"] + + known_params[fmt.specifier](fmt, arg) + + string.sprintf(components["back"], rest, original)); + } + }; + /** + * an implementation of c printf + * @param {string} string format string + * @param {array} args arguments which should be filled into + * @returns {string} + */ + function printf(format, args) { + console.log(string.sprintf(format, args)); + } + string.printf = printf; + })(string = lib_plankton.string || (lib_plankton.string = {})); +})(lib_plankton || (lib_plankton = {})); +var sprintf = lib_plankton.string.sprintf; +var printf = lib_plankton.string.printf; +/* +This file is part of »bacterio-plankton:string«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:string« is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +»bacterio-plankton:string« is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with »bacterio-plankton:string«. If not, see . + */ +var make_logger = (function () { + var _loggers = {}; + var make_logger = function (prefix, current_loglevel) { + var log = []; + var level = [ + "LOG", "INFO", "WARNING", "DEBUG" + ]; + var logger = function (obj, lvl) { + var txt = obj.txt || obj; + if (lvl == void 0) + lvl = 0; + var date = new Date(); + log.push({ + "message": sprintf("%s [%s:%s] %s", [date.toString(), level[lvl], prefix, txt]), + "timeStamp": +(date) + }); + if (lvl <= current_loglevel) { + var msg = ["[" + prefix + "]", txt]; + if (obj.arg) + msg = ["[" + prefix + "]"].concat(Array.prototype.slice.call(obj.arg)); + if (lvl === 0) + console["_log"].apply(console, msg); + else if (lvl === 1) + console["_info"].apply(console, msg); + else if (lvl === 2) + console["_warn"].apply(console, msg); + else if (lvl >= 3) + console["_log"].apply(console, msg); + } + }; + _loggers[prefix] = { + "logger": logger, + "log": log + }; + return logger; + }; + make_logger["loggers"] = _loggers; + make_logger["complete_log"] = function () { + var logs = Object.keys(_loggers) + .reduce(function (p, c) { + return [].concat(p, _loggers[c].log); + }, []); + logs.sort(function (x, y) { + return ((x.timeStamp > y.timeStamp) ? -1 : +1); + }); + return logs.map(function (x, i, a) { + return x.message; + }); + }; + if ( /*!track_exports*/true) { + var _log_all = function (log, lvl, next = function () { }) { + return function () { + var msg = []; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] === "string") { + msg.push(arguments[i]); + } + else { + msg.push(JSON.stringify(arguments[i])); + } + } + var obj = { + txt: msg.join("\t"), + arg: arguments + }; + log(obj, lvl); + next(); + }; + }; + { + var __warn = make_logger("deprecated console.warn", 99); + var __error = make_logger("deprecated console.error", 99); + var __log = make_logger("deprecated console.log", 99); + var __info = make_logger("deprecated console.info", 99); + // bad ass + console["_log"] = console.log; + console["_error"] = console.error; + console["_warn"] = console.warn; + console["_info"] = console.info; + /* + console["log"] = _log_all(__log, 0); + console["error"] = _log_all(__error, 2); + console["warn"] = _log_all(__warn, 2); + console["info"] = _log_all(__info, 0); + */ + } + /* + { + make_logger["send_log"] = function(){ + eml_log( + function () { + alert("fehlerbericht wurde gesendet!"); + } + ); + }; + var error_log = make_logger("global.error", 99); + window.onerror = _log_all( + error_log, + 1, + function(){ + if (global_config == undefined) { + return false; + } + if (global_config.report_error) { + make_logger["send_log"](); + } + } + ); + } + */ + } + return make_logger; +})(); +/* +This file is part of »bacterio-plankton:database«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:database« 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:database« 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:database«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var database; + (function (database) { + /** + */ + let enum_type; + (function (enum_type) { + enum_type["boolean"] = "boolean"; + enum_type["integer"] = "integer"; + enum_type["string_short"] = "string_short"; + enum_type["string_medium"] = "string_medium"; + enum_type["string_long"] = "string_long"; + enum_type["float"] = "float"; + })(enum_type = database.enum_type || (database.enum_type = {})); + })(database = lib_plankton.database || (lib_plankton.database = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:storage«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:storage« 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:storage« 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:storage«. If not, see . + */ +/* +This file is part of »bacterio-plankton:storage«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:storage« 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:storage« 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:storage«. If not, see . + */ +/* +This file is part of »bacterio-plankton:storage«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:storage« 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:storage« 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:storage«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var storage; + (function (storage) { + var memory; + (function (memory) { + /** + * @author fenris + */ + function make(parameters) { + return { + "data": {} + }; + } + memory.make = make; + /** + * @author fenris + */ + function clear(subject) { + subject.data = {}; + } + memory.clear = clear; + /** + * @author fenris + */ + function write(subject, key, value) { + var exists = (key in subject.data); + subject.data[key] = value; + return exists; + } + memory.write = write; + /** + * @author fenris + */ + function delete_(subject, key) { + if (!(key in subject.data)) { + throw (new Error("no value for key '" + key + "'")); + } + else { + delete subject.data[key]; + } + } + memory.delete_ = delete_; + /** + * @author fenris + */ + function read(subject, key) { + if (!(key in subject.data)) { + throw (new Error("no value for key '" + key + "'")); + } + else { + return subject.data[key]; + } + } + memory.read = read; + /** + * @author fenris + */ + function list(subject) { + return Object.keys(subject.data); + } + memory.list = list; + /** + * @author fenris + */ + function search(subject, term) { + return (list(subject) + .map(function (key) { return ({ "key": key, "preview": key }); })); + } + memory.search = search; + /** + * @author fenris + */ + function implementation_chest(parameters) { + function wrap(core) { + return (new Promise(function (resolve, reject) { resolve(core()); })); + } + var subject = make(parameters); + return { + "setup": function (input) { return Promise.resolve(undefined); }, + "clear": function () { return wrap(function () { return clear(subject); }); }, + "write": function (key, value) { return wrap(function () { return write(subject, key, value); }); }, + "delete": function (key) { return wrap(function () { return delete_(subject, key); }); }, + "read": function (key) { return wrap(function () { return read(subject, key); }); }, + "search": function (term) { return wrap(function () { return search(subject, term); }); } + }; + } + memory.implementation_chest = implementation_chest; + })(memory = storage.memory || (storage.memory = {})); + })(storage = lib_plankton.storage || (lib_plankton.storage = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:storage«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:storage« 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:storage« 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:storage«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var storage; + (function (storage) { + var memory; + (function (memory) { + /** + * @author fenris + */ + var class_chest = /** @class */ (function () { + function class_chest(parameters) { + this.subject = memory.make(parameters); + } + class_chest.prototype.setup = function (input) { return Promise.resolve(undefined); }; + class_chest.prototype.clear = function () { memory.clear(this.subject); return Promise.resolve(undefined); }; + class_chest.prototype.write = function (key, value) { return Promise.resolve(memory.write(this.subject, key, value)); }; + class_chest.prototype["delete"] = function (key) { memory.delete_(this.subject, key); return Promise.resolve(undefined); }; + class_chest.prototype.read = function (key) { return Promise.resolve(memory.read(this.subject, key)); }; + class_chest.prototype.search = function (term) { return Promise.resolve(memory.search(this.subject, term)); }; + return class_chest; + }()); + memory.class_chest = class_chest; + })(memory = storage.memory || (storage.memory = {})); + })(storage = lib_plankton.storage || (lib_plankton.storage = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:storage«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:storage« 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:storage« 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:storage«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var storage; + (function (storage) { + var localstorage; + (function (localstorage) { + /** + * @author fenris + */ + function make(parameters) { + parameters = Object.assign({ + "corner": "plankton" + }, parameters); + return { + "corner": parameters.corner + }; + } + localstorage.make = make; + /** + */ + function compose_full_key(subject, key) { + return (subject.corner + "_" + key); + } + /** + */ + function decompose_full_key(subject, full_key) { + var parts = full_key.split("_"); + return ((parts[0] === subject.corner) + ? parts.slice(1).join("_") + : null); + } + /** + * @author fenris + */ + function has(subject, key) { + return localStorage.hasOwnProperty(compose_full_key(subject, key)); + } + /** + * @author fenris + */ + function clear(subject) { + (Object.keys(localStorage) + .map(function (x) { return decompose_full_key(subject, x); }) + .filter(function (x) { return (x !== null); }) + .forEach(function (x) { return localStorage.removeItem(x); })); + } + localstorage.clear = clear; + /** + * @author fenris + */ + function write(subject, key, item) { + var exists = has(subject, key); + localStorage.setItem(compose_full_key(subject, key), item); + return exists; + } + localstorage.write = write; + /** + * @author fenris + */ + function delete_(subject, key) { + localStorage.removeItem(compose_full_key(subject, key)); + } + localstorage.delete_ = delete_; + /** + * @author fenris + */ + function read(subject, key) { + var full_key = compose_full_key(subject, key); + if (!localStorage.hasOwnProperty(full_key)) { + throw (new Error("not found")); + } + else { + return localStorage.getItem(full_key); + } + } + localstorage.read = read; + /** + * @author fenris + */ + function list(subject) { + return (Object.keys(localStorage) + .map(function (x) { return decompose_full_key(subject, x); }) + .filter(function (x) { return (x !== null); })); + } + localstorage.list = list; + /** + */ + function implementation_chest(parameters) { + function wrap(core) { + return (new Promise(function (resolve, reject) { resolve(core()); })); + } + var subject = make(parameters); + return { + "setup": function (input) { return Promise.resolve(undefined); }, + "clear": function () { return wrap(function () { return clear(subject); }); }, + "write": function (key, item) { return wrap(function () { return write(subject, key, item); }); }, + "delete": function (key) { return wrap(function () { return delete_(subject, key); }); }, + "read": function (key) { return wrap(function () { return read(subject, key); }); }, + "search": function (term) { return Promise.resolve(list(subject) + .map(function (key) { return ({ "key": key, "preview": key }); })); } + }; + } + localstorage.implementation_chest = implementation_chest; + })(localstorage = storage.localstorage || (storage.localstorage = {})); + })(storage = lib_plankton.storage || (lib_plankton.storage = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:storage«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:storage« 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:storage« 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:storage«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var storage; + (function (storage) { + var localstorage; + (function (localstorage) { + /** + * uses the browsers localstorage as chest + * + * @author fenris + */ + var class_chest = /** @class */ (function () { + function class_chest(parameters) { + this.subject = localstorage.make(parameters); + } + class_chest.prototype.setup = function (input) { return Promise.resolve(undefined); }; + class_chest.prototype.clear = function () { return Promise.resolve(localstorage.clear(this.subject)); }; + class_chest.prototype.write = function (key, value) { return Promise.resolve(localstorage.write(this.subject, key, value)); }; + class_chest.prototype["delete"] = function (key) { return Promise.resolve(localstorage.delete_(this.subject, key)); }; + class_chest.prototype.read = function (key) { return Promise.resolve(localstorage.read(this.subject, key)); }; + class_chest.prototype.search = function (term) { + return Promise.resolve(localstorage.list(this.subject) + .map(function (key) { return ({ "key": key, "preview": key }); })); + }; + return class_chest; + }()); + localstorage.class_chest = class_chest; + })(localstorage = storage.localstorage || (storage.localstorage = {})); + })(storage = lib_plankton.storage || (lib_plankton.storage = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-input«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-input« 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:zoo-input« 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:zoo-input«. If not, see . + */ +/* +This file is part of »bacterio-plankton:zoo-input«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-input« 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:zoo-input« 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:zoo-input«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_input; + (function (zoo_input) { + /** + * @author fenris + */ + class class_input_wrapped { + /** + */ + constructor(core, wrap, unwrap, options = {}) { + options = Object.assign({}, options); + this.core = core; + this.wrap = wrap; + this.unwrap = unwrap; + } + /** + * [implementation] + */ + setup(parent) { + return this.core.setup(parent); + } + /** + * [implementation] + */ + read() { + return (this.core.read() + .then(value_inner => Promise.resolve(this.wrap(value_inner)))); + } + /** + * [implementation] + */ + write(value) { + return this.core.write(this.unwrap(value)); + } + } + zoo_input.class_input_wrapped = class_input_wrapped; + })(zoo_input = lib_plankton.zoo_input || (lib_plankton.zoo_input = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-input«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-input« 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:zoo-input« 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:zoo-input«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_input; + (function (zoo_input) { + /** + * @author fenris + */ + class class_input_hidden { + /** + */ + constructor(options = {}) { + options = Object.assign({ + "initial_value": null, + }, options); + this.dom_input = null; + this.value = options.initial_value; + } + /** + * [implementation] + */ + setup(parent) { + this.dom_input = document.createElement("input"); + this.dom_input.setAttribute("type", "hidden"); + parent.appendChild(this.dom_input); + return Promise.resolve(undefined); + } + /** + * [implementation] + */ + read() { + return Promise.resolve(this.value); + } + /** + * [implementation] + */ + write(value) { + this.value = value; + return Promise.resolve(undefined); + } + } + zoo_input.class_input_hidden = class_input_hidden; + })(zoo_input = lib_plankton.zoo_input || (lib_plankton.zoo_input = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-input«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-input« 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:zoo-input« 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:zoo-input«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_input; + (function (zoo_input) { + /** + * @author fenris + * @todo abstract + */ + class class_input_text { + /** + */ + constructor(options = {}) { + options = Object.assign({ + "read_only": false, + "pattern": null, + // "autocompletion_list": null, + }, options); + this.read_only = options.read_only; + this.pattern = options.pattern; + // this.autocompletion_list = options.autocompletion_list; + this.dom_input = null; + } + /** + * [implementation] + */ + setup(parent) { + this.dom_input = document.createElement("input"); + this.dom_input.setAttribute("type", "text"); + { + if (!this.read_only) { + // do nothing + } + else { + this.dom_input.setAttribute("disabled", "disabled"); + } + } + { + if (this.pattern === null) { + // do nothing + } + else { + this.dom_input.setAttribute("pattern", this.pattern); + } + } + { + /* + if (this.autocompletion_list === null) { + // do nothing + } + else { + const autocomplete : class_autocomplete = new class_autocomplete( + this.dom_input, + this.autocompletion_list + ); + autocomplete.init(); + } + */ + } + parent.appendChild(this.dom_input); + return Promise.resolve(undefined); + } + /** + * [implementation] + */ + read() { + return Promise.resolve(this.dom_input.value); + } + /** + * [implementation] + */ + write(value) { + this.dom_input.value = value; + return Promise.resolve(undefined); + } + } + zoo_input.class_input_text = class_input_text; + })(zoo_input = lib_plankton.zoo_input || (lib_plankton.zoo_input = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-input«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-input« 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:zoo-input« 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:zoo-input«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_input; + (function (zoo_input) { + /** + * @author fenris + */ + class class_input_email { + /** + */ + constructor() { + this.dom_input = null; + } + /** + * [implementation] + */ + setup(parent) { + this.dom_input = document.createElement("input"); + this.dom_input.setAttribute("type", "email"); + parent.appendChild(this.dom_input); + return Promise.resolve(undefined); + } + /** + * [implementation] + */ + read() { + return Promise.resolve(this.dom_input.value); + } + /** + * [implementation] + */ + write(value) { + this.dom_input.value = value; + return Promise.resolve(undefined); + } + } + zoo_input.class_input_email = class_input_email; + })(zoo_input = lib_plankton.zoo_input || (lib_plankton.zoo_input = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-input«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-input« 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:zoo-input« 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:zoo-input«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_input; + (function (zoo_input) { + /** + * @author fenris + */ + class class_input_textarea { + /** + */ + constructor() { + this.dom_textarea = null; + } + /** + * [implementation] + */ + setup(parent) { + this.dom_textarea = document.createElement("textarea"); + parent.appendChild(this.dom_textarea); + return Promise.resolve(undefined); + } + /** + * [implementation] + */ + read() { + return Promise.resolve(this.dom_textarea.value); + } + /** + * [implementation] + */ + write(value) { + this.dom_textarea.value = value; + return Promise.resolve(undefined); + } + } + zoo_input.class_input_textarea = class_input_textarea; + })(zoo_input = lib_plankton.zoo_input || (lib_plankton.zoo_input = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-input«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-input« 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:zoo-input« 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:zoo-input«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_input; + (function (zoo_input) { + /** + */ + function value_decode(datestring) { + const parts = datestring.split("-"); + return { + "year": parseInt(parts[0]), + "month": parseInt(parts[1]), + "day": parseInt(parts[2]), + }; + } + /** + */ + function value_encode(date) { + return lib_plankton.string.coin("{{year}}-{{month}}-{{day}}", { + "year": date.year.toFixed(0).padStart(4, "0"), + "month": date.month.toFixed(0).padStart(2, "0"), + "day": date.day.toFixed(0).padStart(2, "0"), + }); + } + /** + * @author fenris + */ + class class_input_date { + /** + */ + constructor(options = {}) { + options = Object.assign({ + "required": false, + }, options); + this.required = options.required; + this.dom_input = null; + } + /** + * [implementation] + */ + setup(parent) { + this.dom_input = document.createElement("input"); + this.dom_input.setAttribute("type", "date"); + if (!this.required) { + // do nothing + } + else { + this.dom_input.setAttribute("required", "required"); + } + parent.appendChild(this.dom_input); + return Promise.resolve(undefined); + } + /** + * [implementation] + */ + read() { + if (this.required && (!this.dom_input.reportValidity())) { + return Promise.reject("required"); + } + else { + return Promise.resolve((this.dom_input.value === "") + ? null + : value_decode(this.dom_input.value)); + } + } + /** + * [implementation] + */ + write(value) { + this.dom_input.value = ((value === null) + ? "" + : value_encode(value)); + return Promise.resolve(undefined); + } + } + zoo_input.class_input_date = class_input_date; + })(zoo_input = lib_plankton.zoo_input || (lib_plankton.zoo_input = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-input«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-input« 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:zoo-input« 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:zoo-input«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_input; + (function (zoo_input) { + /** + * @author fenris + * @todo abstract + */ + class class_input_number { + /** + */ + constructor(options = {}) { + options = Object.assign({ + "read_only": false, + "step": null, + }, options); + this.read_only = options.read_only; + this.step = options.step; + this.dom_input = null; + } + /** + * [implementation] + */ + setup(parent) { + this.dom_input = document.createElement("input"); + this.dom_input.setAttribute("type", "number"); + // readonly + { + if (!this.read_only) { + // do nothing + } + else { + this.dom_input.setAttribute("disabled", "disabled"); + } + } + // step + { + if (this.step === null) { + // do nothing + } + else { + this.dom_input.setAttribute("step", this.step.toString()); + } + } + parent.appendChild(this.dom_input); + return Promise.resolve(undefined); + } + /** + * [implementation] + */ + read() { + return Promise.resolve(Number(this.dom_input.value)); + } + /** + * [implementation] + */ + write(value) { + this.dom_input.value = value.toString(); + return Promise.resolve(undefined); + } + } + zoo_input.class_input_number = class_input_number; + })(zoo_input = lib_plankton.zoo_input || (lib_plankton.zoo_input = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-input«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-input« 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:zoo-input« 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:zoo-input«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_input; + (function (zoo_input) { + /** + * @author fenris + */ + class class_input_checkbox { + /** + */ + constructor() { + this.dom_input = null; + } + /** + * [implementation] + */ + setup(parent) { + this.dom_input = document.createElement("input"); + this.dom_input.setAttribute("type", "checkbox"); + // this.dom_input.style.display = "initial"; // n3o!!! + parent.appendChild(this.dom_input); + return Promise.resolve(undefined); + } + /** + * [implementation] + */ + read() { + return Promise.resolve(this.dom_input.checked); + } + /** + * [implementation] + */ + write(value) { + this.dom_input.checked = value; + return Promise.resolve(undefined); + } + } + zoo_input.class_input_checkbox = class_input_checkbox; + })(zoo_input = lib_plankton.zoo_input || (lib_plankton.zoo_input = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-input«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-input« 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:zoo-input« 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:zoo-input«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_input; + (function (zoo_input) { + /** + * @author fenris + */ + class class_input_selection { + /** + */ + constructor(options) { + this.options = options; + this.dom_select = null; + } + /** + * [implementation] + */ + setup(parent) { + this.dom_select = document.createElement("select"); + this.options.forEach((option) => { + let dom_option = document.createElement("option"); + dom_option.setAttribute("value", option.value); + dom_option.textContent = option.label; + this.dom_select.appendChild(dom_option); + }); + parent.appendChild(this.dom_select); + return Promise.resolve(undefined); + } + /** + * [implementation] + */ + read() { + return Promise.resolve(this.dom_select.value); + } + /** + * [implementation] + */ + write(value) { + this.dom_select.value = value; + return Promise.resolve(undefined); + } + } + zoo_input.class_input_selection = class_input_selection; + })(zoo_input = lib_plankton.zoo_input || (lib_plankton.zoo_input = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-input«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-input« 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:zoo-input« 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:zoo-input«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_input; + (function (zoo_input) { + /** + * @author fenris + */ + class class_input_enumeration { + /** + */ + constructor(options) { + this.options = options; + this.dom_inputs = []; + } + /** + * [implementation] + * @todo unique name + */ + setup(parent) { + let dom_container = document.createElement("div"); + dom_container.classList.add("plankton_input_enumeration"); + const name = "radio"; + this.options.forEach((option) => { + let dom_label = document.createElement("label"); + let dom_input = document.createElement("input"); + dom_input.setAttribute("type", "radio"); + dom_input.setAttribute("name", name); + dom_input.setAttribute("value", option.value); + dom_label.appendChild(dom_input); + let dom_span = document.createElement("span"); + dom_span.textContent = option.label; + dom_label.appendChild(dom_span); + dom_container.appendChild(dom_label); + this.dom_inputs.push(dom_input); + }); + parent.appendChild(dom_container); + return Promise.resolve(undefined); + } + /** + * [implementation] + */ + read() { + const active = (this.dom_inputs + .filter(dom_input => dom_input.checked) + .map(dom_input => dom_input.value)); + if (active.length != 1) { + return Promise.reject("nothing picked"); + } + else { + return Promise.resolve(active[0]); + } + } + /** + * [implementation] + */ + write(value) { + this.dom_inputs.forEach(dom_input => { + dom_input.checked = (value === dom_input.value); + }); + return Promise.resolve(undefined); + } + } + zoo_input.class_input_enumeration = class_input_enumeration; + })(zoo_input = lib_plankton.zoo_input || (lib_plankton.zoo_input = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-input«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-input« 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:zoo-input« 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:zoo-input«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_input; + (function (zoo_input) { + /** + * @author fenris + */ + class class_input_list { + /** + */ + constructor(element_input_factory, options = {}) { + options = Object.assign({ + "translations": { + "add": "add", + "remove": "remove", + }, + }, options); + this.element_input_factory = element_input_factory; + this.elements = []; + this.elements_container_dom = null; + this.translations = options.translations; + } + /** + */ + clear() { + this.elements_container_dom.innerHTML = ""; + this.elements = []; + return Promise.resolve(undefined); + } + /** + */ + async add() { + // model + let element_dom = document.createElement("div"); + const input = this.element_input_factory(); + this.elements.push({ "dom": element_dom, "input": input }); + // view & control + { + element_dom.classList.add("plankton_input_list_element"); + // remover + { + let remover_dom = document.createElement("button"); + remover_dom.classList.add("plankton_input_list_button"); + remover_dom.classList.add("plankton_input_list_element_remover"); + remover_dom.setAttribute("title", this.translations.remove); + remover_dom.textContent = "x"; + remover_dom.addEventListener("click", (event) => { + event.preventDefault(); + const index = this.elements.findIndex(element => (element.input === input)); + const element = this.elements[index]; + this.elements_container_dom.removeChild(element.dom); + this.elements.splice(index, 1); + }); + element_dom.appendChild(remover_dom); + } + // input + { + let input_dom = document.createElement("div"); + input_dom.classList.add("plankton_input_list_element_input"); + await input.setup(input_dom); + element_dom.appendChild(input_dom); + } + this.elements_container_dom.appendChild(element_dom); + } + return Promise.resolve(input); + } + /** + * [implementation] + */ + setup(parent) { + let container_dom = document.createElement("div"); + container_dom.classList.add("plankton_input_list"); + // elements + { + this.elements_container_dom = document.createElement("div"); + this.elements_container_dom.classList.add("plankton_input_list_elements"); + container_dom.appendChild(this.elements_container_dom); + } + // foot + { + let footer_dom = document.createElement("div"); + footer_dom.classList.add("plankton_input_list_foot"); + // adder + { + let adder_dom = document.createElement("button"); + adder_dom.classList.add("plankton_input_list_button"); + adder_dom.classList.add("plankton_input_list_adder"); + adder_dom.setAttribute("title", this.translations.add); + adder_dom.textContent = "+"; + adder_dom.addEventListener("click", (event) => { + event.preventDefault(); + this.add(); + }); + footer_dom.appendChild(adder_dom); + } + container_dom.appendChild(footer_dom); + } + parent.appendChild(container_dom); + return Promise.resolve(undefined); + } + /** + * [implementation] + */ + read() { + return (Promise.all(this.elements + .map((element, index) => (element.input.read() + .then((element_value) => Promise.resolve({ + "index": index, + "value": element_value, + }))))) + .then((elements) => Promise.resolve(elements + .sort((x, y) => ((x.index <= y.index) ? 0 : 1)) + .map(element => element.value)))); + } + /** + * [implementation] + */ + write(value) { + return (this.clear() + .then(() => Promise.all(value + .map((element_value) => (this.add() + .then(element_input => element_input.write(element_value)))))) + .then(() => Promise.resolve(undefined))); + } + } + zoo_input.class_input_list = class_input_list; + })(zoo_input = lib_plankton.zoo_input || (lib_plankton.zoo_input = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-input«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-input« 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:zoo-input« 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:zoo-input«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_input; + (function (zoo_input) { + /** + * @author fenris + */ + class class_input_password { + /** + */ + constructor() { + this.dom_input = null; + } + /** + * [implementation] + */ + setup(parent) { + this.dom_input = document.createElement("input"); + this.dom_input.setAttribute("type", "password"); + parent.appendChild(this.dom_input); + return Promise.resolve(undefined); + } + /** + * [implementation] + */ + read() { + return Promise.resolve(this.dom_input.value); + } + /** + * [implementation] + */ + write(value) { + this.dom_input.value = value; + return Promise.resolve(undefined); + } + } + zoo_input.class_input_password = class_input_password; + })(zoo_input = lib_plankton.zoo_input || (lib_plankton.zoo_input = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-input«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-input« 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:zoo-input« 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:zoo-input«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_input; + (function (zoo_input) { + /** + * @author fenris + */ + class class_input_switch { + /** + */ + constructor() { + this.dom_element = null; + this.value = false; + } + /** + * [implementation] + */ + setup(parent) { + this.dom_element = document.createElement("input"); + this.dom_element.setAttribute("type", "text"); + this.dom_element.setAttribute("readonly", "readonly"); + this.dom_element.addEventListener("click", (event) => { + this.write(!this.value); + }); + parent.appendChild(this.dom_element); + return Promise.resolve(undefined); + } + /** + * [implementation] + */ + read() { + return Promise.resolve(this.value); + } + /** + * [implementation] + */ + write(value) { + this.value = value; + if (value) { + this.dom_element.value = "✔"; + } + else { + this.dom_element.value = " "; + } + return Promise.resolve(undefined); + } + } + zoo_input.class_input_switch = class_input_switch; + })(zoo_input = lib_plankton.zoo_input || (lib_plankton.zoo_input = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-input«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-input« 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:zoo-input« 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:zoo-input«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_input; + (function (zoo_input) { + /** + */ + function value_encode(time) { + return lib_plankton.string.coin("{{hour}}:{{minute}}", { + "hour": time.hour.toFixed(0).padStart(2, "0"), + "minute": time.minute.toFixed(0).padStart(2, "0"), + }); + } + /** + */ + function value_decode(timestring) { + const parts = timestring.split(":"); + return { + "hour": parseInt(parts[0]), + "minute": parseInt(parts[1]), + "second": 0, + }; + } + /** + * @author fenris + */ + class class_input_time { + /** + */ + constructor() { + this.dom_input = null; + } + /** + * [implementation] + */ + setup(parent) { + this.dom_input = document.createElement("input"); + this.dom_input.setAttribute("type", "time"); + parent.appendChild(this.dom_input); + return Promise.resolve(undefined); + } + /** + * [implementation] + */ + read() { + return Promise.resolve((this.dom_input.value === "") + ? null + : value_decode(this.dom_input.value)); + } + /** + * [implementation] + */ + write(value) { + this.dom_input.value = ((value === null) + ? "" + : value_encode(value)); + return Promise.resolve(undefined); + } + } + zoo_input.class_input_time = class_input_time; + })(zoo_input = lib_plankton.zoo_input || (lib_plankton.zoo_input = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-input«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-input« 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:zoo-input« 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:zoo-input«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_input; + (function (zoo_input) { + /** + * @author fenris + */ + class class_input_group { + /** + */ + constructor(fields_raw) { + this.fields = (fields_raw + .map(field_raw => ({ + "name": field_raw.name, + "input": field_raw.input, + "label": (field_raw.label ?? null), + "help": (field_raw.help ?? null), + }))); + } + /** + * [implementation] + */ + async setup(parent) { + let dom_group = document.createElement("div"); + dom_group.classList.add("plankton_input_group"); + await Promise.all(this.fields.map(async (field) => { + let dom_field = document.createElement("div"); + dom_field.classList.add("plankton_input_group_field"); + dom_field.setAttribute("rel", field.name); + await Promise.all([ + // label + new Promise((resolve, reject) => { + if (field.label === null) { + // do nothing + } + else { + let dom_label = document.createElement("label"); + dom_label.classList.add("plankton_input_group_field_label"); + dom_label.textContent = field.label; + dom_field.appendChild(dom_label); + } + resolve(undefined); + }), + // help + new Promise((resolve, reject) => { + if (field.help === null) { + // do nothing + } + else { + let dom_help = document.createElement("span"); + dom_help.classList.add("plankton_input_group_field_help"); + dom_help.textContent = "(?)"; + dom_help.setAttribute("title", field.help); + dom_field.appendChild(dom_help); + } + resolve(undefined); + }), + // input + field.input.setup(dom_field), + ]); + dom_group.appendChild(dom_field); + return Promise.resolve(undefined); + })); + parent.appendChild(dom_group); + return Promise.resolve(undefined); + } + /** + * [implementation] + */ + async read() { + return (Promise.all(this.fields.map((field) => (field.input.read() + .then((value) => Promise.resolve({ "key": field.name, "value": value }))))) + .then(pairs => Promise.resolve(Object.fromEntries(pairs.map((pair) => ([pair.key, pair.value])))))); + } + /** + * [implementation] + */ + write(value) { + return (Promise.resolve(Object.entries(value).map(([key, value]) => ({ "key": key, "value": value }))) + .then((pairs) => Promise.all(pairs.map((pair) => (Promise.all(this.fields.filter((field) => (field.name === pair.key)) + .map((field) => field.input.write(pair.value))) + .then(() => Promise.resolve(undefined)))))) + .then(() => Promise.resolve(undefined))); + } + } + zoo_input.class_input_group = class_input_group; + })(zoo_input = lib_plankton.zoo_input || (lib_plankton.zoo_input = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-form«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-form« 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:zoo-form« 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:zoo-form«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_form; + (function (zoo_form) { + /** + */ + function make(method, fields, encode, decode, options = {}) { + options = Object.assign({ + "class_prefix": "plankton_form_", + }, options); + return { + "method": method, + "fields": fields.map(field_raw => ({ + "name": field_raw.name, + "type": field_raw.type, + "label": (field_raw.label ?? null), + })), + "encode": encode, + "decode": decode, + "class_prefix": options.class_prefix, + "root_element": null, + }; + } + zoo_form.make = make; + /** + */ + function make_simple(method, fields, options = {}) { + options = Object.assign({ + "class_prefix": "plankton_form_", + }, options); + return { + "method": method, + "fields": fields.map(field_raw => ({ + "name": field_raw.name, + "type": field_raw.type, + "label": (field_raw.label ?? null), + })), + "encode": x => x, + "decode": x => x, + "class_prefix": options.class_prefix, + "root_element": null, + }; + } + zoo_form.make_simple = make_simple; + /** + */ + function class_name(subject, name) { + return lib_plankton.string.coin("{{class_prefix}}{{name}}", { + "class_prefix": subject.class_prefix, + "name": name, + }); + } + /** + */ + function field_input(subject, field) { + return subject.root_element.querySelector(lib_plankton.string.coin(".{{class}}[name=\"{{name}}\"]", { + "class": class_name(subject, "input"), + "name": field.name, + })); + } + /** + */ + function clear(subject) { + subject.fields.forEach(field => { + switch (field.type) { + default: { + field_input(subject, field).value = ""; + break; + } + case "checkbox": { + field_input(subject, field).checked = false; + break; + } + } + }); + } + zoo_form.clear = clear; + /** + */ + function write(subject, value) { + let raw = subject.encode(value); + subject.fields.forEach(field => { + switch (field.type) { + default: { + field_input(subject, field).value = raw[field.name]; + break; + } + case "checkbox": { + field_input(subject, field).checked = (raw[field.name] === "on"); + break; + } + } + }); + } + zoo_form.write = write; + /** + */ + function read(subject) { + let raw = {}; + subject.fields.forEach(field => { + switch (field.type) { + default: { + raw[field.name] = field_input(subject, field).value; + break; + } + case "checkbox": { + raw[field.name] = (field_input(subject, field).checked ? "on" : "off"); + break; + } + } + }); + const value = subject.decode(raw); + return value; + } + zoo_form.read = read; + /** + */ + async function render(subject, target) { + let element_form = document.createElement("form"); + element_form.classList.add(class_name(subject, "form")); + subject.fields.forEach(field => { + let element_field = document.createElement("div"); + element_field.classList.add(class_name(subject, "field")); + // label + { + let element_label = document.createElement("label"); + element_label.classList.add(class_name(subject, "label")); + element_field.appendChild(element_label); + element_label.textContent = (field.label + ?? + field.name.split("_").join(" ")); + } + // input + { + let element_input = document.createElement("input"); + element_input.classList.add(class_name(subject, "input")); + element_input.setAttribute("name", field.name); + element_input.setAttribute("type", field.type); + element_field.appendChild(element_input); + } + element_form.appendChild(element_field); + }); + subject.root_element = element_form; + target.appendChild(element_form); + return Promise.resolve(undefined); + } + zoo_form.render = render; + })(zoo_form = lib_plankton.zoo_form || (lib_plankton.zoo_form = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-form«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-form« 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:zoo-form« 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:zoo-form«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_form; + (function (zoo_form) { + /** + * @author fenris + */ + class class_form { + /** + */ + constructor(encode, decode, input, actions) { + this.encode = encode; + this.decode = decode; + this.input = input; + this.actions = actions; + } + /** + */ + async setup(parent) { + let dom_form = document.createElement("form"); + dom_form.classList.add("plankton_form"); + // input + { + let dom_container = document.createElement("div"); + dom_container.classList.add("plankton_form_input"); + await this.input.setup(dom_container); + dom_form.appendChild(dom_container); + } + // actions + { + let dom_container = document.createElement("div"); + dom_container.classList.add("plankton_form_actions"); + this.actions.forEach((action) => { + let dom_button = document.createElement("button"); + // dom_button.setAttribute("type", "submit"); + dom_button.textContent = action.label; + if (action.target !== undefined) { + dom_button.setAttribute("formaction", action.target); + } + if (action.procedure !== undefined) { + dom_button.addEventListener("click", (event) => { + event.preventDefault(); + action.procedure(() => this.input_read(), () => this.input_read_raw()); + }); + } + dom_container.appendChild(dom_button); + }); + dom_form.appendChild(dom_container); + } + parent.appendChild(dom_form); + } + /** + */ + input_read_raw() { + return this.input.read(); + } + /** + */ + async input_read() { + return this.decode(await this.input.read()); + } + /** + */ + input_write(value) { + return this.input.write(this.encode(value)); + } + } + zoo_form.class_form = class_form; + })(zoo_form = lib_plankton.zoo_form || (lib_plankton.zoo_form = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-search«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-search« 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:zoo-search« 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:zoo-search«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_search; + (function (zoo_search) { + /** + */ + function class_name(subject, name) { + return lib_plankton.string.coin("{{class_prefix}}{{name}}", { + "class_prefix": subject.class_prefix, + "name": name, + }); + } + /** + */ + function make(routine, options) { + options = Object.assign({ + "encode_item": (item) => JSON.stringify(item), + "hooks_select": [], + "hooks_begin": [], + "hooks_end": [], + "class_prefix": "plankton_search_", + }, options); + return { + "routine": routine, + "encode_item": options.encode_item, + "hooks_select": options.hooks_select, + "hooks_begin": options.hooks_begin, + "hooks_end": options.hooks_end, + "class_prefix": options.class_prefix, + "root_element": null, + "state": null, + }; + } + zoo_search.make = make; + /** + */ + function hook_begin(subject, action) { + subject.hooks_begin.push(action); + } + zoo_search.hook_begin = hook_begin; + /** + */ + function hook_end(subject, action) { + subject.hooks_end.push(action); + } + zoo_search.hook_end = hook_end; + /** + */ + function hook_select(subject, action) { + subject.hooks_select.push(action); + } + zoo_search.hook_select = hook_select; + /** + */ + function clear(subject) { + // term + { + let term_element = subject.root_element.querySelector("." + class_name(subject, "input")); + term_element.value = ""; + } + // list + { + let list_element = subject.root_element.querySelector("." + class_name(subject, "hits")); + list_element.innerHTML = ""; + } + return Promise.resolve(undefined); + } + /** + */ + async function fill(subject, term) { + subject.hooks_begin.forEach(action => { action(term); }); + // term + { + let term_element = subject.root_element.querySelector("." + class_name(subject, "input")); + term_element.setAttribute("placeholder", "search"); + term_element.value = term; + } + // list + { + let list_element = subject.root_element.querySelector("." + class_name(subject, "hits")); + list_element.innerHTML = "searching …"; + const hits = await subject.routine(term); + list_element.innerHTML = ""; + hits.forEach(item => { + let item_element = document.createElement("li"); + item_element.classList.add(class_name(subject, "item")); + item_element.textContent = subject.encode_item(item); + item_element.addEventListener("click", () => { + subject.hooks_select.forEach(action => { action(item); }); + }); + list_element.appendChild(item_element); + }); + } + // external + { + subject.hooks_end.forEach(action => { action(); }); + } + return Promise.resolve(undefined); + } + /** + */ + async function set_state(subject, state) { + if ((subject.state !== null) + && + (state.term === subject.state.term)) { + // do nothing + } + else { + subject.state = state; + if (state.term === null) { + await clear(subject); + } + else { + await fill(subject, state.term); + } + } + return Promise.resolve(undefined); + } + zoo_search.set_state = set_state; + /** + */ + async function render(subject, target, options = {}) { + options = Object.assign({ + "state": { "term": null }, + }, options); + let container_element = document.createElement("div"); + container_element.classList.add(class_name(subject, "search")); + // form + { + let form_element = document.createElement("form"); + // term + { + let term_element = document.createElement("input"); + term_element.setAttribute("type", "search"); + term_element.setAttribute("name", "term"); + term_element.classList.add(class_name(subject, "input")); + form_element.appendChild(term_element); + } + // submit + { + let submit_element = document.createElement("input"); + submit_element.setAttribute("type", "submit"); + submit_element.classList.add(class_name(subject, "submit")); + form_element.appendChild(submit_element); + } + form_element.addEventListener("submit", (event) => { + event.preventDefault(); + const form_data = new FormData(form_element); + const term = form_data.get("term"); + set_state(subject, { "term": term }); + }); + container_element.appendChild(form_element); + } + // hits + { + let hits_element = document.createElement("ul"); + hits_element.classList.add(class_name(subject, "hits")); + container_element.appendChild(hits_element); + } + subject.root_element = container_element; + target.appendChild(container_element); + await set_state(subject, options.state); + return Promise.resolve(undefined); + } + zoo_search.render = render; + })(zoo_search = lib_plankton.zoo_search || (lib_plankton.zoo_search = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-editor«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-editor« 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:zoo-editor« 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:zoo-editor«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_editor; + (function (zoo_editor) { + /** + */ + let enum_mode; + (function (enum_mode) { + enum_mode["find"] = "find"; + enum_mode["view"] = "view"; + enum_mode["make"] = "make"; + })(enum_mode = zoo_editor.enum_mode || (zoo_editor.enum_mode = {})); + ; + /** + */ + let enum_action; + (function (enum_action) { + enum_action["keep"] = "keep"; + enum_action["save"] = "save"; + enum_action["delete"] = "delete"; + enum_action["find"] = "find"; + enum_action["make"] = "make"; + })(enum_action = zoo_editor.enum_action || (zoo_editor.enum_action = {})); + ; + /** + */ + let enum_function; + (function (enum_function) { + enum_function["seek"] = "seek"; + enum_function["read"] = "read"; + enum_function["create"] = "create"; + enum_function["update"] = "update"; + enum_function["delete"] = "delete"; + })(enum_function = zoo_editor.enum_function || (zoo_editor.enum_function = {})); + ; + /** + */ + function make(store, form, options = {}) { + options = Object.assign({ + "functions": [ + enum_function.seek, + enum_function.read, + enum_function.create, + enum_function.update, + enum_function.delete, + ], + "encode_hit": (hit) => lib_plankton.string.coin("[{{key}}] {{preview}}", { + "key": JSON.stringify(hit.key), + "preview": JSON.stringify(hit.preview), + }), + "hook_switch": null, + "class_prefix": "plankton_editor_", + }, options); + return { + "functions": options.functions, + "store": store, + /* + // wrap store in order to restrict access according to allowed functions + "store": new RestrictedStorage( + store, + ArrayListHelper::map( + $this->functions, + function (string $function): string {return self::$actionMap[$function];} + ) + ), + */ + "search": lib_plankton.zoo_search.make((term) => store.search(term), { + "encode_item": options.encode_hit, + }), + "form": form, + "hook_switch": options.hook_switch, + "state": null, + "class_prefix": options.class_prefix, + "root_element": null, + }; + } + zoo_editor.make = make; + /** + */ + function class_name(subject, name) { + return lib_plankton.string.coin("{{class_prefix}}{{name}}", { + "class_prefix": subject.class_prefix, + "name": name, + }); + } + /** + */ + function map_function_to_store_action(function_) { + switch (function_) { + case enum_function.seek: return "seek"; + case enum_function.read: return "read"; + case enum_function.create: return "create"; + case enum_function.update: return "update"; + case enum_function.delete: return "delete"; + } + } + /** + */ + function map_mode_to_functions(mode) { + switch (mode) { + case enum_mode.find: return [enum_function.seek]; + case enum_mode.view: return [enum_function.read]; + case enum_mode.make: return [enum_function.create]; + } + } + /** + */ + function map_mode_to_actions(mode) { + switch (mode) { + case enum_mode.find: return [enum_action.make]; + case enum_mode.view: return [enum_action.save, enum_action.delete, enum_action.find, enum_action.make]; + case enum_mode.make: return [enum_action.keep, enum_action.find]; + } + } + /** + */ + function map_action_to_class_body(action) { + return ("action_" + action); + } + /** + */ + function wait(subject, mode) { + subject.root_element.classList.toggle("waiting", mode); + // loader + { + // view + { + subject.root_element.querySelector("." + class_name(subject, "loader")).style.display = (mode ? "" : "none"); + } + } + /* + // search + { + // view + { + ( + subject.root_element.querySelector( + "." + class_name(subject, "search") + ) as HTMLElement + ).style.display = ((! mode) ? "" : "none"); + } + } + // form + { + // view + { + ( + subject.root_element.querySelector( + "." + class_name(subject, "form") + ) as HTMLElement + ).style.display = ((! mode) ? "" : "none"); + } + } + // actions + { + // view + { + ( + subject.root_element.querySelector( + "." + class_name(subject, "actions") + ) as HTMLElement + ).style.display = ((! mode) ? "" : "none"); + } + } + */ + } + /** + */ + async function set_state(subject, state) { + const state_old = subject.state; + subject.state = state; + // container + { + if (state_old === null) { + // do nothing + } + else { + subject.root_element.classList.remove(state_old.mode); + } + subject.root_element.classList.add(state.mode); + } + // search + { + // model + { + await lib_plankton.zoo_search.set_state(subject.search, state.search_state); + } + // view + { + subject.root_element.querySelector("." + class_name(subject, "search")).style.display = ([enum_mode.find].includes(state.mode) + ? "" + : "none"); + } + } + // form + { + // model + { + if (state.key === null) { + lib_plankton.zoo_form.clear(subject.form); + } + else { + lib_plankton.zoo_form.write(subject.form, await subject.store.read(state.key)); + } + } + // view + { + subject.root_element.querySelector("." + class_name(subject, "form")).style.display = ([enum_mode.view, enum_mode.make].includes(state.mode) + ? "" + : "none"); + } + } + // actions + { + // view + { + [ + enum_action.keep, + enum_action.save, + enum_action.delete, + enum_action.find, + enum_action.make, + ] + .forEach(action => { + subject.root_element.querySelector("." + class_name(subject, map_action_to_class_body(action))).style.visibility = (map_mode_to_actions(state.mode).includes(action) + ? "" + : "hidden"); + }); + } + } + // external + { + if (subject.hook_switch === null) { + // do nothing + } + else { + subject.hook_switch(state); + } + } + } + /** + */ + async function render(subject, target, options = {}) { + options = Object.assign({ + "state": { + "mode": enum_mode.find, + "key": null, + "search_state": { "term": null }, + }, + }, options); + subject.state = options.state; + const element_all = document.createElement("div"); + element_all.classList.add(class_name(subject, "container")); + { + // loader + { + const container_element = document.createElement("div"); + container_element.classList.add(class_name(subject, "loader")); + // text + { + const text_element = document.createElement("div"); + text_element.textContent = "…"; + container_element.appendChild(text_element); + } + element_all.appendChild(container_element); + } + // search + { + const container_element = document.createElement("div"); + container_element.classList.add(class_name(subject, "search")); + // search core + { + lib_plankton.zoo_search.hook_select(subject.search, async (hit) => { + wait(subject, true); + await set_state(subject, { + "mode": enum_mode.view, + "key": hit.key, + "search_state": { "term": null }, + }); + wait(subject, false); + }); + lib_plankton.zoo_search.hook_begin(subject.search, (term) => { + set_state(subject, { + "mode": subject.state.mode, + "key": subject.state.key, + "search_state": { "term": term }, + }); + }); + await lib_plankton.zoo_search.render(subject.search, container_element, { + "state": options.state.search_state, + }); + } + element_all.appendChild(container_element); + } + // form + { + const container_element = document.createElement("div"); + container_element.classList.add(class_name(subject, "form")); + // form core + { + await lib_plankton.zoo_form.render(subject.form, container_element); + } + element_all.appendChild(container_element); + } + // actions + { + let container_element = document.createElement("div"); + container_element.classList.add(class_name(subject, "actions")); + { + [ + { + "value": enum_action.find, + // TODO translate + "label": "search", + "procedure": async () => { + wait(subject, true); + set_state(subject, { + "mode": enum_mode.find, + "key": null, + "search_state": { "term": null }, + }); + wait(subject, false); + }, + }, + { + "value": enum_action.make, + // TODO translate + "label": "new", + "procedure": async () => { + wait(subject, true); + set_state(subject, { + "mode": enum_mode.make, + "key": null, + "search_state": { "term": null }, + }); + wait(subject, false); + }, + }, + { + "value": enum_action.keep, + // TODO translate + "label": "save", + "procedure": async () => { + wait(subject, true); + const value = lib_plankton.zoo_form.read(subject.form); + const key = await subject.store.create(value); + set_state(subject, { + "mode": enum_mode.view, + "key": key, + "search_state": { "term": null }, + }); + wait(subject, false); + }, + }, + { + "value": enum_action.save, + // TODO translate + "label": "apply", + "procedure": async () => { + wait(subject, true); + const value = lib_plankton.zoo_form.read(subject.form); + await subject.store.update(subject.state.key, value); + /* + set_state( + subject, + { + "mode": enum_mode.view, + "key": subject.state.key, + "search_state": {"term": null}, + } + ); + */ + wait(subject, false); + }, + }, + { + "value": enum_action.delete, + // TODO translate + "label": "delete", + "procedure": async () => { + if (confirm("sure?")) { + wait(subject, true); + await subject.store.delete(subject.state.key); + set_state(subject, { + "mode": enum_mode.find, + "key": null, + "search_state": { "term": null }, + }); + wait(subject, false); + } + else { + // no nothing + } + }, + }, + ] + .forEach(action => { + let button_element = document.createElement("button"); + button_element.classList.add(class_name(subject, "action")); + button_element.classList.add(class_name(subject, map_action_to_class_body(action.value))); + button_element.textContent = action.label; + button_element.addEventListener("click", () => { + action.procedure(); + }); + container_element.appendChild(button_element); + }); + } + element_all.appendChild(container_element); + } + target.appendChild(element_all); + } + subject.root_element = element_all; + set_state(subject, options.state); + wait(subject, false); + } + zoo_editor.render = render; + })(zoo_editor = lib_plankton.zoo_editor || (lib_plankton.zoo_editor = {})); +})(lib_plankton || (lib_plankton = {})); +/* +This file is part of »bacterio-plankton:zoo-page«. + +Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR' + + +»bacterio-plankton:zoo-page« 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:zoo-page« 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:zoo-page«. If not, see . + */ +var lib_plankton; +(function (lib_plankton) { + var zoo_page; + (function (zoo_page) { + /** + */ + zoo_page._pool = {}; + /** + */ + let _fallback = null; + /** + */ + let _current = null; + /** + */ + let _target_element = null; + /** + */ + function encode(location) { + return ("#" + + + ([location.name] + .concat(Object.entries(location.parameters) + .filter(([key, value]) => (value !== null)) + .map(([key, value]) => (key + "=" + value))))); + } + zoo_page.encode = encode; + /** + */ + function decode(encoded) { + if (encoded === "") { + return null; + } + else { + if (!encoded.startsWith("#")) { + return null; + } + else { + const parts = encoded.slice(1).split(","); + return { + "name": parts[0], + "parameters": Object.fromEntries(parts.slice(1) + .map(part => { + const parts_ = part.split("="); + return [parts_[0], parts_[1]]; + })), + }; + } + } + } + /** + * renders a page to the main element + */ + async function load(location) { + // _target_element.innerHTML = "[loading …]"; + _target_element.innerHTML = ""; + if (location === null) { + // do nothing + } + else { + if (!(location.name in zoo_page._pool)) { + _target_element.innerHTML = "not found"; + } + else { + await zoo_page._pool[location.name](location.parameters, _target_element); + _current = location; + } + } + } + /** + */ + function add_nav_entry(location, options = {}) { + options = Object.assign({ + "label": null, + }, options); + let ul_element = document.querySelector("nav > ul"); + { + let li_element = document.createElement("li"); + { + let a_element = document.createElement("a"); + a_element.setAttribute("href", encode(location)); + a_element.textContent = (options.label ?? location.name); + li_element.appendChild(a_element); + } + ul_element.appendChild(li_element); + } + } + zoo_page.add_nav_entry = add_nav_entry; + /** + * retrieves the location from the set URL + */ + function get() { + return decode(window.location.hash); + } + /** + * encodes a location in the URL and loads it + */ + function set(location) { + window.location.hash = encode(location); + } + zoo_page.set = set; + /** + */ + function register(location_name, handler, options = {}) { + options = Object.assign({}, options); + zoo_page._pool[location_name] = handler; + } + zoo_page.register = register; + /** + */ + function init(target_element, options = {}) { + options = Object.assign({ + "pool": {}, + "fallback": null, + }, options); + _target_element = target_element; + _fallback = options.fallback; + Object.entries(options.pool).forEach(([location_name, handler]) => { + register(location_name, handler); + }); + window.addEventListener("hashchange", () => { + const location_old = _current; + const location_new = (get() ?? _fallback); + if (((location_old === null) + && + (location_new !== null)) + || + ((location_old !== null) + && + (location_new !== null) + && + (location_old.name !== location_new.name))) { + load(location_new); + } + else { + // do nothing + } + }); + } + zoo_page.init = init; + /** + */ + function start() { + const location = (get() ?? _fallback); + set(location); + load(location); + } + zoo_page.start = start; + })(zoo_page = lib_plankton.zoo_page || (lib_plankton.zoo_page = {})); +})(lib_plankton || (lib_plankton = {})); diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..e69de29 diff --git a/source/logic/backend.ts b/source/logic/backend.ts new file mode 100644 index 0000000..9894618 --- /dev/null +++ b/source/logic/backend.ts @@ -0,0 +1,323 @@ +namespace _aum.backend +{ + + /** + */ + var _session_key_chest : lib_plankton.storage.type_chest; + + + /** + * @todo use backend call + */ + export async function logged_in( + ) : Promise + { + let session_key : (null | string); + try { + session_key = (await _session_key_chest.read("session_key")); + } + catch (error) { + session_key = null; + } + return Promise.resolve(session_key !== null); + } + + + /** + */ + export function init( + ) : Promise + { + _session_key_chest = lib_plankton.storage.localstorage.implementation_chest( + { + "corner": "aum", + } + ); + return Promise.resolve(undefined); + } + + + /** + */ + async function abstract_call( + http_method : string, + path : string, + options : { + data ?: type_input; + } = {} + ) : Promise + { + options = Object.assign( + { + "data": null, + }, + options + ); + + let session_key : (null | string); + try { + session_key = (await _session_key_chest.read("session_key")); + } + catch (error) { + session_key = null; + } + + const without_content : boolean = ["HEAD","OPTIONS","GET"].includes(http_method); + return ( + fetch( + lib_plankton.string.coin( + ("{{scheme}}://{{host}}:{{port}}{{path_base}}{{path_action}}"), + { + "scheme": _aum.conf.get().backend.scheme, + "host": _aum.conf.get().backend.host, + "port": _aum.conf.get().backend.port.toFixed(0), + "path_base": _aum.conf.get().backend.path_base, + "path_action": path, + } + ), + { + "method": http_method, + "headers": Object.assign( + {}, + ((! without_content) ? {"Content-Type": "application/json"} : {}), + ((session_key !== null) ? {"X-Session-Key": session_key} : {}) + ), + "body": ( + without_content + ? null + : JSON.stringify(options.data) + ), + } + ) + .then( + x => { + if ((x.status >= 200) && (x.status < 300)) { + return x.json(); + } + else { + return Promise.reject(new Error("unexpected response status code")); + } + } + ) + ); + } + + + /** + */ + export async function login( + name : string, + password : string + ) : Promise + { + const session_key : string = await abstract_call<{name : string; password : string;}, string>( + "POST", + "/session/begin", + { + "data": { + "name": name, + "password": password, + } + } + ); + await _session_key_chest.write("session_key", session_key); + } + + + /** + */ + export async function logout( + ) : Promise + { + try { + await abstract_call( + "DELETE", + "/session/end" + ); + } + catch (error) { + // do nothing + } + await _session_key_chest.delete("session_key"); + } + + + /** + */ + export async function email( + receivers : Array, + subject : string, + content : string + ) : Promise + { + return ( + abstract_call( + "POST", + "/email", + { + "data": { + "receivers": receivers, + "subject": subject, + "content": content, + }, + } + ) + ); + } + + + /** + */ + export async function verification_get( + data : any + ) : Promise + { + return ( + abstract_call( + "POST", + "/verification/get", + { + "data": { + "data": data, + }, + } + ) + ); + } + + + /** + */ + export async function verification_check( + data : any, + verification : string + ) : Promise + { + return ( + abstract_call( + "POST", + "/verification/check", + { + "data": { + "data": data, + "verification": verification, + } + } + ) + ); + } + + + /** + */ + export async function member_list( + ) : Promise> + { + return ( + abstract_call( + "GET", + "/member" + ) + ); + } + + + /** + */ + export async function member_get( + id : int + ) : Promise + { + return abstract_call( + "GET", + "/member/" + id.toFixed(0) + ); + } + + + /** + */ + export async function member_add( + data : Record + ) : Promise + { + return abstract_call( + "POST", + "/member", + { + "data": { + "membership_number": data["membership_number"], + "enabled": data["enabled"], + "name_real_value": data["name_real_value"], + "name_real_extension": data["name_real_extension"], + "name_display": data["name_display"], + "name_login": data["name_login"], + "password_image": null, + "email_address_private_value": data["email_address_private_value"], + "email_address_numberbased_use": data["email_address_numberbased_use"], + "email_address_namebased_use": data["email_address_namebased_use"], + "email_redirect_to_private": data["email_redirect_to_private"], + "salutation": data["salutation"], + } + } + ); + } + + + /** + */ + export async function member_modify( + id : int, + data : Record + ) : Promise + { + return abstract_call( + "PATCH", + "/member/" + id.toFixed(0), + { + "data": { + "membership_number": data["membership_number"], + "enabled": data["enabled"], + "name_real_value": data["name_real_value"], + "name_real_extension": data["name_real_extension"], + "name_display": data["name_display"], + "name_login": data["name_login"], + "password_image": null, + "email_address_private_value": data["email_address_private_value"], + "email_address_numberbased_use": data["email_address_numberbased_use"], + "email_address_namebased_use": data["email_address_namebased_use"], + "email_redirect_to_private": data["email_redirect_to_private"], + "salutation": data["salutation"], + } + } + ); + } + + + /** + */ + export async function member_register( + id : int, + verification : string, + data : { + name_login : string; + name_display : string; + salutation : string; + email_mode : ("none" | "number" | "number_and_name"); + email_redirect : boolean; + password : string; + } + ) : Promise + { + return ( + abstract_call( + "POST", + "/member/register/" + id.toFixed(0) + "?verification=" + verification, + { + "data": data, + } + ) + ); + } + +} diff --git a/source/logic/conf.ts b/source/logic/conf.ts new file mode 100644 index 0000000..5f850d7 --- /dev/null +++ b/source/logic/conf.ts @@ -0,0 +1,43 @@ +namespace _aum.conf +{ + + /** + */ + export type type_data = { + backend : { + scheme : string; + host : string; + port : int; + path_base : string; + }; + }; + + + /** + */ + var _data : (null | type_data) = null; + + + /** + */ + export async function load( + ) : Promise + { + _data = lib_plankton.json.decode(await lib_plankton.file.read("conf.json")); + } + + + /** + */ + export function get( + ) : type_data + { + if (_data === null) { + throw (new Error("conf not loaded yet")); + } + else { + return _data; + } + } + +} diff --git a/source/logic/main.ts b/source/logic/main.ts new file mode 100644 index 0000000..423c2dc --- /dev/null +++ b/source/logic/main.ts @@ -0,0 +1,105 @@ + +/** + */ +function template_request( + id : string +) : DocumentFragment +{ + let dom_template = document.querySelector("template#" + id); + // return template["content"].cloneNode(true); + return (document.importNode(dom_template["content"], true) as DocumentFragment) +} + + +/** + */ +async function update_nav( + options : { + mode ?: string; + } = {} +) : Promise +{ + options = Object.assign( + { + "mode": ((await _aum.backend.logged_in()) ? "logged_in" : "logged_out"), + }, + options + ); + let dom_body = document.querySelector("body"); + if (options.mode === null) { + dom_body.removeAttribute("rel"); + } + else { + dom_body.setAttribute("rel", options.mode); + } +} + + +/** + */ +function setup_nav( +) : void +{ + const entries : Array< + { + location : lib_plankton.zoo_page.type_location; + label : string; + classes : Array; + } + > = [ + { + "location": {"name": "login", "parameters": {}}, + "label": "Anmelden", + "classes": ["logged_out"], + }, + { + "location": {"name": "logout", "parameters": {}}, + "label": "Abmelden", + "classes": ["logged_in"], + }, + { + "location": {"name": "create", "parameters": {}}, + "label": "Mitglied anlegen", + "classes": ["logged_in"], + }, + { + "location": {"name": "members", "parameters": {}}, + "label": "Mitglieder-Übersicht", + "classes": ["logged_in"], + }, + ]; + + let dom_ul : HTMLElement = document.querySelector("nav > ul"); + entries.forEach( + entry => { + let dom_li : HTMLElement = document.createElement("li"); + { + let dom_a : HTMLElement = document.createElement("a"); + dom_a.textContent = entry.label; + dom_a.setAttribute("href", lib_plankton.zoo_page.encode(entry.location)); + entry.classes.forEach(class_ => {dom_a.classList.add(class_);}); + dom_li.appendChild(dom_a); + } + dom_ul.appendChild(dom_li); + } + ); + update_nav(); +} + + +/** + */ +async function main( +) : Promise +{ + await _aum.conf.load(); + await _aum.backend.init(); + await lib_plankton.zoo_page.init( + document.querySelector("main"), + { + "fallback": {"name": "index", "parameters": {}}, + } + ); + setup_nav(); + lib_plankton.zoo_page.start(); +} diff --git a/source/logic/pages/create.ts b/source/logic/pages/create.ts new file mode 100644 index 0000000..4dd826b --- /dev/null +++ b/source/logic/pages/create.ts @@ -0,0 +1,72 @@ +lib_plankton.zoo_page.register( + "create", + (parameters, target_element) => { + const form = new lib_plankton.zoo_form.class_form< + { + membership_number : string; + name_real_value : string; + email_address_private_value : (null | string); + }, + { + membership_number : string; + name_real_value : string; + email_address_private_value : string; + } + >( + value => ({ + "membership_number": value.membership_number, + "name_real_value": value.name_real_value, + "email_address_private_value": (value.email_address_private_value ?? ""), + }), + representation => ({ + "membership_number": representation.membership_number, + "name_real_value": representation.name_real_value, + "email_address_private_value": representation.email_address_private_value, + }), + new lib_plankton.zoo_input.class_input_group( + [ + { + "name": "membership_number", + "input": new lib_plankton.zoo_input.class_input_text(), + "label": "Mitgliedsnummer", + }, + { + "name": "name_real_value", + "input": new lib_plankton.zoo_input.class_input_text(), + "label": "Echter Name", + }, + { + "name": "email_address_private_value", + "input": new lib_plankton.zoo_input.class_input_text(), + "label": "Private E-Mail-Adresse", + }, + ] + ), + [ + { + "label": "Senden", + "procedure": async (get_value, get_representation) => { + const value = await get_value(); + const id = await _aum.backend.member_add( + { + "membership_number": value.membership_number, + "name_real_value": value.name_real_value, + "email_address_private_value": value.email_address_private_value, + "name_real_extension": null, + "name_display": null, + "name_login": null, + "salutation": null, + "password_image": null, + "email_address_numberbased_use": false, + "email_address_namebased_use": false, + "email_redirect_to_private": false, + } + ); + lib_plankton.zoo_page.set({"name": "view", "parameters": {"id": id}}); + }, + } + ] + ); + form.setup(target_element as HTMLElement); + } +); diff --git a/source/logic/pages/index.ts b/source/logic/pages/index.ts new file mode 100644 index 0000000..a6ff0d0 --- /dev/null +++ b/source/logic/pages/index.ts @@ -0,0 +1,5 @@ +lib_plankton.zoo_page.register( + "index", + (parameters, target_element) => { + } +); diff --git a/source/logic/pages/login.ts b/source/logic/pages/login.ts new file mode 100644 index 0000000..0371723 --- /dev/null +++ b/source/logic/pages/login.ts @@ -0,0 +1,62 @@ +lib_plankton.zoo_page.register( + "login", + (parameters, target_element) => { + target_element.appendChild(template_request("login")); + + const form = new lib_plankton.zoo_form.class_form< + { + name : string; + password : string; + }, + { + name : string; + password : string; + } + >( + x => x, + x => x, + new lib_plankton.zoo_input.class_input_group( + [ + { + "name": "name", + "input": new lib_plankton.zoo_input.class_input_text(), + "label": "Name", + }, + { + "name": "password", + "input": new lib_plankton.zoo_input.class_input_password(), + "label": "Passwort", + }, + ] + ), + [ + { + "label": "Anmelden", + "procedure": async (get_value, get_representation) => { + const value = await get_value(); + ( + _aum.backend.login(value.name, value.password) + .then( + () => { + lib_plankton.zoo_page.set({"name": "index", "parameters": {}}); + update_nav({"mode": "logged_in"}); + } + ) + .catch( + (error) => { + form.input_write( + { + "name": value.name, + "password": "" + } + ); + } + ) + ); + }, + } + ] + ); + form.setup(target_element.querySelector(".login-form") as HTMLElement); + } +); diff --git a/source/logic/pages/logout.ts b/source/logic/pages/logout.ts new file mode 100644 index 0000000..de45a3f --- /dev/null +++ b/source/logic/pages/logout.ts @@ -0,0 +1,8 @@ +lib_plankton.zoo_page.register( + "logout", + async (parameters, target_element) => { + await _aum.backend.logout(); + lib_plankton.zoo_page.set({"name": "index", "parameters": {}}); + update_nav({"mode": "logged_in"}); + } +); diff --git a/source/logic/pages/members.ts b/source/logic/pages/members.ts new file mode 100644 index 0000000..ae12b38 --- /dev/null +++ b/source/logic/pages/members.ts @@ -0,0 +1,219 @@ +lib_plankton.zoo_page.register( + "members", + (parameters, target_element) => { + const state : (null | any) = ( + ("state" in parameters) + ? lib_plankton.json.decode(lib_plankton.base64.decode(parameters["state"])) + : null + ); + + const set_state = function (state) { + target_element.querySelector(".members").setAttribute("rel", state); + }; + + let _id : (null | int) = null; + + const editor : lib_plankton.zoo_editor.type_editor = lib_plankton.zoo_editor.make( + { + "setup": (parameters) => Promise.resolve(undefined), + "search": async (term) => lib_plankton.call.convey( + await _aum.backend.member_list(), + [ + // (raw as Array<{id : int; preview : any;}>) + x => x.filter( + ( + (term === null) + || + (term === "") + ) + ? (entry => true) + : ( + (term.length < 2) + ? (entry => false) + : ( + entry => ( + entry.preview["membership_number"].includes(term) + || + entry.preview["name_real_value"].toLowerCase().includes(term) + ) + ) + ) + ), + x => x.map( + entry => ({ + "key": entry.id, + "preview": entry.preview, + }) + ), + ] + ), + "read": (key) => _aum.backend.member_get(key), + "create": (value) => /*_aum.backend.member_add(value)*/Promise.reject(new Error("missing")), + "update": (key, value) => _aum.backend.member_modify(key, value), + "delete": (key) => /*_aum.backend.member_remove(key)*/Promise.reject(new Error("missing")), + }, + lib_plankton.zoo_form.make( + "GET", + [ + { + "name": "membership_number", + "type": "text", + "label": "Mitgliedsnummer", + }, + { + "name": "enabled", + "type": "checkbox", + "label": "Für Online-Dienste freischalten", + }, + { + "name": "name_real_value", + "type": "text", + "label": "Echter Name", + }, + { + "name": "name_real_extension", + "type": "text", + "label": "Zusatz für echten Name (für mögliche Dopplung)", + }, + { + "name": "name_display", + "type": "text", + "label": "Anzeigename", + }, + { + "name": "name_login", + "type": "text", + "label": "Anmeldename", + }, + { + "name": "email_address_private_value", + "type": "text", + "label": "Private E-Mail-Adresse", + }, + { + "name": "email_address_numberbased_use", + "type": "checkbox", + "label": "Nummernbasierte E-Mail-Adresse verwenden", + }, + { + "name": "email_address_namebased_use", + "type": "checkbox", + "label": "Namensbasierte E-Mail-Adresse verwenden", + }, + { + "name": "email_redirect_to_private", + "type": "checkbox", + "label": "E-Mails an private Adresse umleiten", + }, + { + "name": "salutation", + "type": "text", + "label": "Anrede/Pronomen", + }, + ], + value => ({ + "enabled": (value.enabled ? "on" : ""), + "membership_number": value.membership_number, + "name_real_value": value.name_real_value, + "name_real_extension": value.name_real_extension, + "name_display": value.name_display, + "name_login": value.name_login, + "email_address_private_value": value.email_address_private_value, + "email_address_numberbased_use": (value.email_address_numberbased_use ? "on" : ""), + "email_address_namebased_use": (value.email_address_namebased_use ? "on" : ""), + "email_redirect_to_private": (value.email_redirect_to_private ? "on" : ""), + "salutation": value.salutation, + }), + raw => ({ + "enabled": (raw["enabled"] === "on"), + "membership_number": raw["membership_number"], + "name_real_value": raw["name_real_value"], + "name_real_extension": raw["name_real_extension"], + "name_display": raw["name_display"], + "name_login": raw["name_login"], + "email_address_private_value": raw["email_address_private_value"], + "email_address_numberbased_use": (raw["email_address_numberbased_use"] === "on"), + "email_address_namebased_use": (raw["email_address_namebased_use"] === "on"), + "email_redirect_to_private": (raw["email_redirect_to_private"] === "on"), + "salutation": raw["salutation"], + }), + { + } + ), + { + "encode_hit": hit => lib_plankton.string.coin( + "{{number}} | {{name}}", + { + "number": hit.preview["membership_number"], + "name": hit.preview["name_real_value"], + } + ), + "hook_switch": (state) => { + _id = state.key; + set_state((_id === null) ? "poor" : "rich"); + const state_encoded : string = lib_plankton.base64.encode(lib_plankton.json.encode(state)); + lib_plankton.zoo_page.set({"name": "members", "parameters": {"state": state_encoded}}); + }, + } + ); + + target_element.appendChild(template_request("members")); + + lib_plankton.zoo_editor.render( + editor, + target_element.querySelector(".members-editor"), + ( + Object.assign( + { + }, + ((state !== null) ? {"state": state} : {}) + ) + ) + ); + + target_element.querySelector(".members-urge_for_registration").addEventListener( + "click", + async () => { + const verification : string = await _aum.backend.verification_get(_id); + const location_encoded : string = lib_plankton.zoo_page.encode( + { + "name": "register", + "parameters": { + "id": _id, + "verification": verification, + } + } + ); + const url_base : string = window.location.href.split("#")[0]; + const url : string = (url_base + location_encoded); + + const data : Record = await lib_plankton.zoo_form.read(editor.form); + + const text_paragraphs : Array = [ + lib_plankton.string.coin( + "Hi, {{name}}!", + { + "name": "data.name_real_value", + } + ), + "Willkommen bei der Linken!", + "Wir als Landesverband Sachsen stellen für unsere Mitglieder verschiedene Online-Dienste zur Verfügung. Dazu gehört eine E-Mail-Adresse bei der Partei, ein Instant Messenger, eine Cloud, ein Wiki und noch einiges mehr.", + "Wenn du die Dienste nutzen möchtest, rufe bitte folgende Adresse auf:", + url, + "Solidarische Grüße, dein Landesverband Sachsen", + ]; + + _aum.backend.email( + [ + data.email_address_private_value, + ], + "DIE LINKE. | Landesverband Sachsen | Registierung für Online-Dienste", + text_paragraphs.join("\n\n"), + ); + // TODO: statt dessen eine E-Mail an die private Adresse des Neumitglieds senden + // target_element.querySelector(".members-result").setAttribute("href", url); + alert(url); + } + ); + } +); diff --git a/source/logic/pages/register.ts b/source/logic/pages/register.ts new file mode 100644 index 0000000..76e63b3 --- /dev/null +++ b/source/logic/pages/register.ts @@ -0,0 +1,132 @@ +lib_plankton.zoo_page.register( + "register", + async (parameters, target_element) => { + const set_state = function (state) { + target_element.querySelector(".register").setAttribute("rel", state); + }; + const set_message = function (message) { + target_element.querySelector(".register-message").textContent = message; + }; + + const id : int = parseInt(parameters["id"]); + const verification : string = parameters["verification"]; + + update_nav({"mode": null}); + + const form = new lib_plankton.zoo_form.class_form( + x => x, + x => x, + new lib_plankton.zoo_input.class_input_group( + [ + { + "name": "id", + "input": new lib_plankton.zoo_input.class_input_hidden(), + }, + { + "name": "verification", + "input": new lib_plankton.zoo_input.class_input_hidden(), + }, + { + "name": "email_mode", + "input": new lib_plankton.zoo_input.class_input_enumeration( + [ + {"value": "none", "label": "keine"}, + {"value": "number", "label": "nur numerische"}, + {"value": "number_and_name", "label": "numerische und namensbasierte"}, + ] + ), + "label": "Partei-E-Mail-Adresse einrichten", + "help": "Die nummernbasierte Partei-E-Mail-Adresse hat folgenden schematischen Aufbau: \"mitglied-@dielinke-sachsen.de\", z.B. \"mitglied-11223344@dielinke-sachsen.de\".\n\nDie namensbasierte Partei-E-Mail-Adresse hat folgenden schematischen Aufbau: \"@dielinke-sachsen.de\". Beispiel: \"Karl Liebknecht\" würde die Adresse \"karl.liebknecht@dielinke-sachsen.de\" bekommen.\n\nDie Partei-E-Mail-Adressen können zum Empfangen von E-Mails verwendet werden. Falls es nötig werden sollte, dass du auch E-Mails mit über die Partei-Adresse verschicken kannst, wende dich bitte an den/die Mitgliederbeauftragte:n!" + }, + { + "name": "email_redirect", + "input": new lib_plankton.zoo_input.class_input_checkbox(), + "label": "eingehende E-Mails zu privater Adresse umleiten", + "help": "Um die bei der Partei-Adresse eingegangenen E-Mails zu lesen, gibt es zwei Wege: Entweder du hinterlegst das zugehörige Konto im E-Mail-Client-Programm deiner Wahl und kümmerst dich selbst darum die E-Mails regelmäßig abzurufen oder die E-Mails werden an deine private Adresse weitergeleitet, sodass sie bei deinen gewöhnlichen E-Mails mit auftauchen.\n\nWenn du dir unsicher bist, empfehlen wir dir die Umleitung anzuschalten.", + }, + { + "name": "name_display", + "input": new lib_plankton.zoo_input.class_input_text(), + "label": "Anzeigename", + "help": "So wirst du bei Online-Diensten anderen angezeigt.", + }, + { + "name": "salutation", + "input": new lib_plankton.zoo_input.class_input_text(), + "label": "Anrede/Pronomen (z.B. 'er/ihn')", + }, + { + "name": "name_login", + "input": new lib_plankton.zoo_input.class_input_text( + { + "pattern": "^[0-9a-zA-Z_]+$", + } + ), + "label": "Anmeldename", + "help": "Dieser Wert ist der Nutzername für die Anmeldung bei den Online-Diensten. Hierfür solltest du etwas kurzes und prägnantes wählen. Diesen Namen bekommt für gewöhnlich niemand zu sehen. Bitte beachte, dass der Name noch verfügbar sein muss!", + }, + { + "name": "password", + "input": new lib_plankton.zoo_input.class_input_password(), + "label": "Passwort", + "help": "Das Passwort für die Anmeldung bei den Online-Diensten", + }, + { + "name": "password_confirmation", + "input": new lib_plankton.zoo_input.class_input_password(), + "label": "Passwort wiederholen", + }, + ] + ), + [ + { + "label": "Senden", + "procedure": async (get_value, get_representation) => { + set_message("wird verarbeitet …"); + set_state("wait"); + + const value : any = await get_value(); + + if (value.password !== value.password_confirmation) { + set_message("Die Passwörter stimmen nicht überein."); + set_state("fill"); + } + else { + try { + await _aum.backend.member_register( + id, + verification, + value + ); + set_message("Danke!"); + set_state("done"); + } + catch (error) { + set_message("Da ist etwas schief gelaufen :/"); + set_state("fill"); + } + } + }, + }, + ] + ); + + target_element.appendChild(template_request("register")); + + await form.setup(target_element.querySelector(".register-form") as HTMLElement); + await form.input_write( + { + "id": id, + "verification": verification, + "name_login": "", + "name_display": "", + "salutation": "", + "email_mode": "number_and_name", + "email_redirect": true, + "password": "", + "password_confirmation": "", + } + ); + set_state("fill"); + }, +); diff --git a/source/structure/index.html.tpl b/source/structure/index.html.tpl new file mode 100644 index 0000000..03dab22 --- /dev/null +++ b/source/structure/index.html.tpl @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + +
+

DIE LINKE. Landesverband Sachsen

+
+
+ +
+
+ + diff --git a/source/style/style.css b/source/style/style.css new file mode 100644 index 0000000..0796591 --- /dev/null +++ b/source/style/style.css @@ -0,0 +1,183 @@ +:root +{ + --hue: 0; +} + +html +{ + font-family: monospace; + font-size: 1.5em; + + background-color: hsl(var(--hue), 0%, 0%); + color: hsl(var(--hue), 0%, 100%); +} + + +body +{ + max-width: 960px; + margin: auto; + padding: 24px; + + background-color: hsl(var(--hue), 0%, 12.5%); + color: hsl(var(--hue), 0%, 87.5%); +} + +body:not([rel="logged_out"]) nav .logged_out {display: none;} +body:not([rel="logged_in"]) nav .logged_in {display: none;} + +a +{ + background-color: hsl(var(--hue), 0%, 12.5%); + + text-decoration: none; +} + +a:not(:hover) +{ + /* + color: hsl(var(--hue), 75%, 50%); + */ + color: hsl(var(--hue), 72.3%, 54.7%); +} + +a:hover +{ + /* + color: hsl(var(--hue), 75%, 75%); + */ + color: hsl(var(--hue), 72.8%, 79.8%) +} + +input[type="text"] +, +input[type="number"] +, +input[type="password"] +{ + background-color: hsl(var(--hue), 0%, 87.5%); + color: hsl(var(--hue), 0%, 12.5%); + + padding: 8px; +} + +nav +{ + border-bottom: 1px solid hsl(var(--hue), 0%, 100%); + margin-bottom: 16px; +} + +nav > ul +{ + list-style-type: none; + margin: 0; + padding: 0; +} + +nav > ul > li +{ + display: inline-block; + margin-right: 16px; + padding: 8px; + + /* + text-transform: uppercase; + */ +} + +/* +nav > ul > li:hover::before +{ + content: "["; +} + +nav > ul > li:hover::after +{ + content: "]"; +} + */ + +.plankton_form_field +{ + margin-bottom: 16px; +} + +.plankton_form_label +{ + display: block; + + font-size: 0.75em; + font-weight: bold; +} + +.plankton_input_group_field +{ + margin-bottom: 16px; +} + +.plankton_input_group_field_label +{ + font-size: 0.75em; + font-weight: bold; + /* + text-transform: capitalize; + */ +} + +.plankton_input_group_field_label + :not(.plankton_input_group_field_help) +{ + display: block; +} + +.plankton_input_group_field_help +{ + margin-left: 8px; + + font-size: 0.75em; + font-weight: bold; + + cursor: help; +} + +.plankton_input_group_field_help + * +{ + display: block; +} + + +.plankton_input_enumeration > * +{ + display: block; +} + +.plankton_editor_actions +{ + margin-top: 16px; +} + +.plankton_editor_action +{ + text-transform: uppercase; + margin: 8px; +} + +.members-result:not([href]) +{ + display: none; +} + +.register:not([rel]) .register-message {display: none;} +.register:not([rel]) .register-form {display: none;} + +.register[rel="fill"] .register-message {} +.register[rel="fill"] .register-form {} + +.register[rel="wait"] .register-message {} +.register[rel="wait"] .register-form {display: none;} + +.register[rel="done"] .register-message {} +.register[rel="done"] .register-form {display: none;} + +.members:not([rel]) .members-extras {display: none;} +.members[rel="poor"] .members-extras {display: none;} +.members[rel="rich"] .members-extras {} diff --git a/tools/build b/tools/build new file mode 100755 index 0000000..c68bc9d --- /dev/null +++ b/tools/build @@ -0,0 +1,5 @@ +#!/usr/bin/env sh + +## exec + +make --file=tools/makefile diff --git a/tools/makefile b/tools/makefile new file mode 100644 index 0000000..ab2c9e5 --- /dev/null +++ b/tools/makefile @@ -0,0 +1,49 @@ +## consts + +dir_lib := lib +dir_source := source +dir_temp := temp +dir_build := build + +cmd_log := echo "--" +cmd_cat := cat +cmd_chmod := chmod +cmd_mkdir := mkdir -p +cmd_cp := cp + + +## rules + +.PHONY: default +default: ${dir_build}/index.html ${dir_build}/logic.js ${dir_build}/style.css + +${dir_build}/index.html: ${dir_source}/structure/index.html.tpl + @ ${cmd_log} "structure …" + @ ${cmd_mkdir} $(dir $@) + @ ${cmd_cat} $^ > $@ + +${dir_temp}/logic-unlinked.js: \ + ${dir_lib}/plankton/plankton.d.ts \ + ${dir_source}/logic/backend.ts \ + ${dir_source}/logic/conf.ts \ + ${dir_source}/logic/pages/index.ts \ + ${dir_source}/logic/pages/login.ts \ + ${dir_source}/logic/pages/logout.ts \ + ${dir_source}/logic/pages/members.ts \ + ${dir_source}/logic/pages/create.ts \ + ${dir_source}/logic/pages/register.ts \ + ${dir_source}/logic/main.ts + @ ${cmd_log} "logic | compile …" + @ ${cmd_mkdir} $(dir $@) + @ tsc --lib es2020,dom $^ --outFile $@ + +${dir_build}/logic.js: ${dir_lib}/plankton/plankton.js ${dir_temp}/logic-unlinked.js + @ ${cmd_log} "logic | link …" + @ ${cmd_mkdir} $(dir $@) + @ ${cmd_cat} $^ > $@ + @ ${cmd_chmod} +x $@ + +${dir_build}/style.css: ${dir_source}/style/style.css + @ ${cmd_log} "style …" + @ ${cmd_mkdir} $(dir $@) + @ ${cmd_cat} $^ > $@ diff --git a/tools/run b/tools/run new file mode 100755 index 0000000..bc2bc74 --- /dev/null +++ b/tools/run @@ -0,0 +1,5 @@ +#!/usr/bin/env sh + +cd build +web-server . 8888 +cd - diff --git a/tools/update-plankton b/tools/update-plankton new file mode 100755 index 0000000..d38aada --- /dev/null +++ b/tools/update-plankton @@ -0,0 +1,26 @@ +#!/usr/bin/env sh + +## consts + +dir=lib/plankton + +modules="" +modules="${modules} base" +modules="${modules} file" +modules="${modules} json" +modules="${modules} base64" +modules="${modules} string" +modules="${modules} storage" +modules="${modules} zoo-input" +modules="${modules} zoo-form" +modules="${modules} zoo-search" +modules="${modules} zoo-editor" +modules="${modules} zoo-page" + + +## exec + +mkdir -p ${dir} +cd ${dir} +ptk bundle web ${modules} +cd - > /dev/null