Merge branch 'main' into task-193

This commit is contained in:
roydfalk 2025-04-03 06:19:47 +00:00
commit b522514c26
23 changed files with 3919 additions and 3020 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -4,6 +4,21 @@
"verbosity": "info", "verbosity": "info",
"verification_secret": null "verification_secret": null
}, },
"log": [
{
"kind": "stdout",
"data": {
"threshold": "info"
}
},
{
"kind": "file",
"data": {
"threshold": "notice",
"path": "/tmp/espe/log.jsonl"
}
}
],
"server": { "server": {
"port": 4916, "port": 4916,
"path_base": "" "path_base": ""

View file

@ -19,17 +19,20 @@ namespace _espe.api
/** /**
*/ */
export function register_member_delete( export function register_member_delete(
rest_subject : lib_plankton.rest.type_rest rest_subject : lib_plankton.rest_http.type_rest
) : void ) : void
{ {
register<null, null>( lib_plankton.rest_http.register<
null,
null
>(
rest_subject, rest_subject,
lib_plankton.http.enum_method.delete, lib_plankton.http.enum_method.delete,
"/member/delete/:id", _espe.api.full_path("/member/delete/:id"),
{ {
"description": "löscht ein vorhandenes Mitglied", "description": () => "löscht ein vorhandenes Mitglied",
"restriction": restriction_logged_in, "restriction": () => restriction_logged_in,
"execution": async ({"path_parameters": path_parameters}) => { "execution": () => async ({"path_parameters": path_parameters}) => {
const member_id : _espe.type.member_id = parseInt(path_parameters["id"]); const member_id : _espe.type.member_id = parseInt(path_parameters["id"]);
await _espe.service.member.remove(member_id); await _espe.service.member.remove(member_id);
return Promise.resolve({ return Promise.resolve({

View file

@ -20,10 +20,10 @@ namespace _espe.api
* @todo zeitliche Begrenzung? * @todo zeitliche Begrenzung?
*/ */
export function register_member_info( export function register_member_info(
rest_subject : lib_plankton.rest.type_rest rest_subject : lib_plankton.rest_http.type_rest
) : void ) : void
{ {
register< lib_plankton.rest_http.register<
int, int,
( (
null null
@ -39,9 +39,9 @@ namespace _espe.api
>( >(
rest_subject, rest_subject,
lib_plankton.http.enum_method.get, lib_plankton.http.enum_method.get,
"/member/info/:id", _espe.api.full_path("/member/info/:id"),
{ {
"description": "gibt Angaben über ein Mitglied aus, die für die Registrierung verwendet werden dürfen", "description": () => "gibt Angaben über ein Mitglied aus, die für die Registrierung verwendet werden dürfen",
"input_schema": () => ({ "input_schema": () => ({
"type": "number", "type": "number",
"nullable": false, "nullable": false,
@ -80,18 +80,18 @@ namespace _espe.api
"email_address_nominal", "email_address_nominal",
] ]
}), }),
"query_parameters": [ "query_parameters": () => [
{ {
"name": "key", "name": "key",
"required": true, "required": true,
"description": "Zugriffs-Schlüssel", "description": "Zugriffs-Schlüssel",
}, },
], ],
"restriction": restriction_verification( "restriction": () => restriction_verification(
stuff => parseInt(stuff.path_parameters["id"]), stuff => parseInt(stuff.path_parameters["id"]),
stuff => stuff.query_parameters["key"] stuff => stuff.query_parameters["key"]
), ),
"execution": async ({"path_parameters": path_parameters, "input": input}) => { "execution": () => async ({"path_parameters": path_parameters, "input": input}) => {
const member_id : _espe.type.member_id = parseInt(path_parameters["id"]); const member_id : _espe.type.member_id = parseInt(path_parameters["id"]);
const data : ( const data : (
null null

View file

@ -19,10 +19,10 @@ namespace _espe.api
/** /**
*/ */
export function register_member_list( export function register_member_list(
rest_subject : lib_plankton.rest.type_rest rest_subject : lib_plankton.rest_http.type_rest
) : void ) : void
{ {
register< lib_plankton.rest_http.register<
null, null,
Array< Array<
{ {
@ -37,10 +37,10 @@ namespace _espe.api
>( >(
rest_subject, rest_subject,
lib_plankton.http.enum_method.get, lib_plankton.http.enum_method.get,
"/member/list", _espe.api.full_path("/member/list"),
{ {
"description": "listet alle Mitglieder auf", "description": () => "listet alle Mitglieder auf",
"query_parameters": [ "query_parameters": () => [
{ {
"name": "search_term", "name": "search_term",
"required": false, "required": false,
@ -88,8 +88,8 @@ namespace _espe.api
], ],
} }
}), }),
"restriction": restriction_logged_in, "restriction": () => restriction_logged_in,
"execution": ({"query_parameters": query_parameters}) => ( "execution": () => ({"query_parameters": query_parameters}) => (
_espe.service.member.list(query_parameters["search_term"] ?? null) _espe.service.member.list(query_parameters["search_term"] ?? null)
.then( .then(
data => Promise.resolve({ data => Promise.resolve({

View file

@ -19,10 +19,10 @@ namespace _espe.api
/** /**
*/ */
export function register_member_modify( export function register_member_modify(
rest_subject : lib_plankton.rest.type_rest rest_subject : lib_plankton.rest_http.type_rest
) : void ) : void
{ {
register< lib_plankton.rest_http.register<
{ {
email_address_private : (null | string); email_address_private : (null | string);
groups ?: Array<string>; groups ?: Array<string>;
@ -33,9 +33,9 @@ namespace _espe.api
>( >(
rest_subject, rest_subject,
lib_plankton.http.enum_method.patch, lib_plankton.http.enum_method.patch,
"/member/modify/:id", _espe.api.full_path("/member/modify/:id"),
{ {
"description": "ändert die Angaben eines vorhandenen Mitglieds", "description": () => "ändert die Angaben eines vorhandenen Mitglieds",
"input_schema": () => ({ "input_schema": () => ({
"nullable": false, "nullable": false,
"type": "object", "type": "object",
@ -71,8 +71,8 @@ namespace _espe.api
"output_schema": () => ({ "output_schema": () => ({
"nullable": true, "nullable": true,
}), }),
"restriction": restriction_logged_in, "restriction": () => restriction_logged_in,
"execution": async ({"path_parameters": path_parameters, "input": input}) => { "execution": () => async ({"path_parameters": path_parameters, "input": input}) => {
if (input === null) { if (input === null) {
return Promise.reject(new Error("impossible")); return Promise.reject(new Error("impossible"));
} }

View file

@ -20,10 +20,10 @@ namespace _espe.api
* @todo ausgeklügelte Durchsatzratenbegrenzung * @todo ausgeklügelte Durchsatzratenbegrenzung
*/ */
export function register_member_password_change_execute( export function register_member_password_change_execute(
rest_subject : lib_plankton.rest.type_rest rest_subject : lib_plankton.rest_http.type_rest
) : void ) : void
{ {
register< lib_plankton.rest_http.register<
{ {
token : string; token : string;
password_new : string; password_new : string;
@ -37,9 +37,9 @@ namespace _espe.api
>( >(
rest_subject, rest_subject,
lib_plankton.http.enum_method.patch, lib_plankton.http.enum_method.patch,
"/member/password_change/execute/:id", _espe.api.full_path("/member/password_change/execute/:id"),
{ {
"description": "Führt eine Passwort-Änderung für ein Mitglied durch", "description": () => "Führt eine Passwort-Änderung für ein Mitglied durch",
"input_schema": () => ({ "input_schema": () => ({
"nullable": false, "nullable": false,
"type": "object", "type": "object",
@ -88,8 +88,8 @@ namespace _espe.api
] ]
} }
}), }),
"restriction": restriction_none, "restriction": () => restriction_none,
"execution": ({"path_parameters": path_parameters, "input": input}) => { "execution": () => ({"path_parameters": path_parameters, "input": input}) => {
if (input === null) { if (input === null) {
return Promise.reject(new Error("impossible")); return Promise.reject(new Error("impossible"));
} }

View file

@ -21,10 +21,10 @@ namespace _espe.api
* @todo captcha * @todo captcha
*/ */
export function register_member_password_change_initialize( export function register_member_password_change_initialize(
rest_subject : lib_plankton.rest.type_rest rest_subject : lib_plankton.rest_http.type_rest
) : void ) : void
{ {
register< lib_plankton.rest_http.register<
{ {
identifier : string; identifier : string;
url_template : string; url_template : string;
@ -33,9 +33,9 @@ namespace _espe.api
>( >(
rest_subject, rest_subject,
lib_plankton.http.enum_method.post, lib_plankton.http.enum_method.post,
"/member/password_change/initialize", _espe.api.full_path("/member/password_change/initialize"),
{ {
"description": "Versucht dem gegebenen Identifikator ein Mitglied zuzuordnen und sendet dem ermittelten Mitglied einen Passwort-Änderungs-Verweis an die hinterlegte private E-Mail-Adresse", "description": () => "Versucht dem gegebenen Identifikator ein Mitglied zuzuordnen und sendet dem ermittelten Mitglied einen Passwort-Änderungs-Verweis an die hinterlegte private E-Mail-Adresse",
"input_schema": () => ({ "input_schema": () => ({
"nullable": false, "nullable": false,
"type": "object", "type": "object",
@ -60,8 +60,8 @@ namespace _espe.api
"output_schema": () => ({ "output_schema": () => ({
"nullable": true "nullable": true
}), }),
"restriction": restriction_none, "restriction": () => restriction_none,
"execution": async ({"input": input}) => { "execution": () => async ({"input": input}) => {
if (input === null) { if (input === null) {
return Promise.reject(new Error("impossible")); return Promise.reject(new Error("impossible"));
} }

View file

@ -19,10 +19,10 @@ namespace _espe.api
/** /**
*/ */
export function register_member_project( export function register_member_project(
rest_subject : lib_plankton.rest.type_rest rest_subject : lib_plankton.rest_http.type_rest
) : void ) : void
{ {
register< lib_plankton.rest_http.register<
{ {
membership_number : (null | string); membership_number : (null | string);
name_real_value : string; name_real_value : string;
@ -38,9 +38,9 @@ namespace _espe.api
>( >(
rest_subject, rest_subject,
lib_plankton.http.enum_method.post, lib_plankton.http.enum_method.post,
"/member/project", _espe.api.full_path("/member/project"),
{ {
"description": "erstellt ein neues Mitglied und gibt die erzeugte ID aus", "description": () => "erstellt ein neues Mitglied und gibt die erzeugte ID aus",
"input_schema": () => ({ "input_schema": () => ({
"type": "object", "type": "object",
"nullable": false, "nullable": false,
@ -84,8 +84,8 @@ namespace _espe.api
"type": "number", "type": "number",
"nullable": false, "nullable": false,
}), }),
"restriction": restriction_logged_in, "restriction": () => restriction_logged_in,
"execution": async ({"input": input}) => { "execution": () => async ({"input": input}) => {
if (input === null) { if (input === null) {
return Promise.reject(new Error("impossible")); return Promise.reject(new Error("impossible"));
} }

View file

@ -19,10 +19,10 @@ namespace _espe.api
/** /**
*/ */
export function register_member_read( export function register_member_read(
rest_subject : lib_plankton.rest.type_rest rest_subject : lib_plankton.rest_http.type_rest
) : void ) : void
{ {
register< lib_plankton.rest_http.register<
null, null,
{ {
membership_number : (null | string); membership_number : (null | string);
@ -44,9 +44,9 @@ namespace _espe.api
>( >(
rest_subject, rest_subject,
lib_plankton.http.enum_method.get, lib_plankton.http.enum_method.get,
"/member/read/:id", _espe.api.full_path("/member/read/:id"),
{ {
"description": "gibt ein Mitglied anhand seiner ID aus", "description": () => "gibt ein Mitglied anhand seiner ID aus",
"output_schema": () => ({ "output_schema": () => ({
"nullable": false, "nullable": false,
"type": "object", "type": "object",
@ -135,8 +135,8 @@ namespace _espe.api
"name_login", "name_login",
] ]
}), }),
"restriction": restriction_logged_in, "restriction": () => restriction_logged_in,
"execution": async ({"path_parameters": path_parameters, "input": input}) => { "execution": () => async ({"path_parameters": path_parameters, "input": input}) => {
const member_id : _espe.type.member_id = parseInt(path_parameters["id"]); const member_id : _espe.type.member_id = parseInt(path_parameters["id"]);
const member_object : _espe.type.member_object = await _espe.service.member.get(member_id); const member_object : _espe.type.member_object = await _espe.service.member.get(member_id);
return Promise.resolve({ return Promise.resolve({

View file

@ -20,10 +20,10 @@ namespace _espe.api
* @todo zeitliche Begrenzung? * @todo zeitliche Begrenzung?
*/ */
export function register_member_register( export function register_member_register(
rest_subject : lib_plankton.rest.type_rest rest_subject : lib_plankton.rest_http.type_rest
) : void ) : void
{ {
register< lib_plankton.rest_http.register<
{ {
email_use_veiled_address : boolean; email_use_veiled_address : boolean;
email_use_nominal_address : boolean; email_use_nominal_address : boolean;
@ -40,9 +40,9 @@ namespace _espe.api
>( >(
rest_subject, rest_subject,
lib_plankton.http.enum_method.post, lib_plankton.http.enum_method.post,
"/member/register/:id", _espe.api.full_path("/member/register/:id"),
{ {
"description": "nimmt zusätzliche Angaben eines Mitglieds entgegen", "description": () => "nimmt zusätzliche Angaben eines Mitglieds entgegen",
"input_schema": () => ({ "input_schema": () => ({
"type": "object", "type": "object",
"nullable": false, "nullable": false,
@ -109,18 +109,18 @@ namespace _espe.api
] ]
} }
}), }),
"query_parameters": [ "query_parameters": () => [
{ {
"name": "key", "name": "key",
"required": true, "required": true,
"description": "Zugriffs-Schlüssel", "description": "Zugriffs-Schlüssel",
}, },
], ],
"restriction": restriction_verification( "restriction": () => restriction_verification(
stuff => parseInt(stuff.path_parameters["id"]), stuff => parseInt(stuff.path_parameters["id"]),
stuff => stuff.query_parameters["key"] stuff => stuff.query_parameters["key"]
), ),
"execution": ({"path_parameters": path_parameters, "input": input}) => { "execution": () => ({"path_parameters": path_parameters, "input": input}) => {
if (input === null) { if (input === null) {
return Promise.reject(new Error("impossible")); return Promise.reject(new Error("impossible"));
} }

View file

@ -19,10 +19,10 @@ namespace _espe.api
/** /**
*/ */
export function register_member_summon( export function register_member_summon(
rest_subject : lib_plankton.rest.type_rest rest_subject : lib_plankton.rest_http.type_rest
) : void ) : void
{ {
lib_plankton.rest.register< lib_plankton.rest_http.register<
{ {
url_template : string; url_template : string;
}, },
@ -36,9 +36,9 @@ namespace _espe.api
lib_plankton.http.enum_method.post, lib_plankton.http.enum_method.post,
_espe.conf.get().server.path_base + "/member/summon/:id", _espe.conf.get().server.path_base + "/member/summon/:id",
{ {
"description": "sendet an ein Mitglied eine E-Mail mit Aufforderung zur Registrierung", "description": () => "sendet an ein Mitglied eine E-Mail mit Aufforderung zur Registrierung",
"restriction": restriction_logged_in, "restriction": () => restriction_logged_in,
"execution": async ({"path_parameters": path_parameters, "input": input}) => { "execution": () => async ({"path_parameters": path_parameters, "input": input}) => {
if (input === null) { if (input === null) {
return Promise.reject(new Error("impossible")); return Promise.reject(new Error("impossible"));
} }

View file

@ -19,10 +19,10 @@ namespace _espe.api
/** /**
*/ */
export function register_meta_ping( export function register_meta_ping(
rest_subject : lib_plankton.rest.type_rest rest_subject : lib_plankton.rest_http.type_rest
) : void ) : void
{ {
lib_plankton.rest.register< lib_plankton.rest_http.register<
null, null,
string string
> >
@ -31,7 +31,7 @@ namespace _espe.api
lib_plankton.http.enum_method.get, lib_plankton.http.enum_method.get,
_espe.conf.get().server.path_base + "/meta/ping", _espe.conf.get().server.path_base + "/meta/ping",
{ {
"description": "sendet ein 'pong' zurück; gedacht um die Erreichbarkeit des Backends zu prüfen", "description": () => "sendet ein 'pong' zurück; gedacht um die Erreichbarkeit des Backends zu prüfen",
"input_schema": () => ({ "input_schema": () => ({
"nullable": true, "nullable": true,
}), }),
@ -39,8 +39,8 @@ namespace _espe.api
"nullable": false, "nullable": false,
"type": "string", "type": "string",
}), }),
"restriction": restriction_none, "restriction": () => restriction_none,
"execution": () => { "execution": () => () => {
return Promise.resolve({ return Promise.resolve({
"status_code": 200, "status_code": 200,
"data": "pong", "data": "pong",

View file

@ -19,10 +19,10 @@ namespace _espe.api
/** /**
*/ */
export function register_meta_spec( export function register_meta_spec(
rest_subject : lib_plankton.rest.type_rest rest_subject : lib_plankton.rest_http.type_rest
) : void ) : void
{ {
lib_plankton.rest.register< lib_plankton.rest_http.register<
null, null,
any any
> >
@ -31,17 +31,17 @@ namespace _espe.api
lib_plankton.http.enum_method.get, lib_plankton.http.enum_method.get,
_espe.conf.get().server.path_base + "/meta/spec", _espe.conf.get().server.path_base + "/meta/spec",
{ {
"description": "gibt die API-Spezifikation im OpenAPI-Format aus", "description": () => "gibt die API-Spezifikation im OpenAPI-Format aus",
"input_schema": () => ({ "input_schema": () => ({
"nullable": true, "nullable": true,
}), }),
"output_schema": () => ({ "output_schema": () => ({
}), }),
"restriction": restriction_none, "restriction": () => restriction_none,
"execution": () => { "execution": () => () => {
return Promise.resolve({ return Promise.resolve({
"status_code": 200, "status_code": 200,
"data": lib_plankton.rest.to_oas(rest_subject), "data": lib_plankton.rest_http.to_oas(rest_subject),
}); });
}, },
} }

View file

@ -19,10 +19,10 @@ namespace _espe.api
/** /**
*/ */
export function register_session_begin( export function register_session_begin(
rest_subject : lib_plankton.rest.type_rest rest_subject : lib_plankton.rest_http.type_rest
) : void ) : void
{ {
lib_plankton.rest.register< lib_plankton.rest_http.register<
{ {
name : string; name : string;
password : string; password : string;
@ -37,7 +37,7 @@ namespace _espe.api
lib_plankton.http.enum_method.post, lib_plankton.http.enum_method.post,
_espe.conf.get().server.path_base + "/session/begin", _espe.conf.get().server.path_base + "/session/begin",
{ {
"description": "führt die Anmeldung am System aus um geschützte Aktionen nutzen zu können", "description": () => "führt die Anmeldung am System aus um geschützte Aktionen nutzen zu können",
"input_schema": () => ({ "input_schema": () => ({
"type": "object", "type": "object",
"properties": { "properties": {
@ -58,8 +58,8 @@ namespace _espe.api
"type": "string", "type": "string",
"description": "der Sitzungs-Schlüssel, der als Header 'X-Session-Key' gesetzt werden muss um Erlaubnis zur Ausführung geschützter Aktionen zu erhalten", "description": "der Sitzungs-Schlüssel, der als Header 'X-Session-Key' gesetzt werden muss um Erlaubnis zur Ausführung geschützter Aktionen zu erhalten",
}), }),
"restriction": restriction_none, "restriction": () => restriction_none,
"execution": async ({"input": input}) => { "execution": () => async ({"input": input}) => {
if (input === null) { if (input === null) {
return Promise.reject(new Error("impossible")); return Promise.reject(new Error("impossible"));
} }

View file

@ -19,23 +19,26 @@ namespace _espe.api
/** /**
*/ */
export function register_session_end( export function register_session_end(
rest_subject : lib_plankton.rest.type_rest rest_subject : lib_plankton.rest_http.type_rest
) : void ) : void
{ {
register<null, null>( lib_plankton.rest_http.register<
null,
null
>(
rest_subject, rest_subject,
lib_plankton.http.enum_method.delete, lib_plankton.http.enum_method.delete,
"/session/end", "/session/end",
{ {
"description": "beendet eine Sitzung", "description": () => "beendet eine Sitzung",
"input_schema": () => ({ "input_schema": () => ({
"type": "null", "type": "null",
}), }),
"output_schema": () => ({ "output_schema": () => ({
"type": "null", "type": "null",
}), }),
"restriction": restriction_logged_in, "restriction": () => restriction_logged_in,
"execution": async (stuff) => { "execution": () => async (stuff) => {
const session : {key : string; value : lib_plankton.session.type_session} = await session_from_stuff(stuff); const session : {key : string; value : lib_plankton.session.type_session} = await session_from_stuff(stuff);
await lib_plankton.session.end(session.key); await lib_plankton.session.end(session.key);
return Promise.resolve({ return Promise.resolve({

View file

@ -20,7 +20,7 @@ namespace _espe.api
* @todo zu plankton auslagern? * @todo zu plankton auslagern?
*/ */
type type_stuff = { type type_stuff = {
version: (null | string); // version: (null | string);
headers: Record<string, string>; headers: Record<string, string>;
path_parameters: Record<string, string>; path_parameters: Record<string, string>;
query_parameters: Record<string, string>; query_parameters: Record<string, string>;
@ -43,9 +43,9 @@ namespace _espe.api
*/ */
/* /*
export function restriction_disjunction( export function restriction_disjunction(
left : lib_plankton.rest.type_restriction<any>, left : lib_plankton.rest_http.type_restriction<any>,
right : lib_plankton.rest.type_restriction<any> right : lib_plankton.rest_http.type_restriction<any>
) : lib_plankton.rest.type_restriction<any> ) : lib_plankton.rest_http.type_restriction<any>
{ {
return ( return (
(stuff) => Promise.any<boolean>( (stuff) => Promise.any<boolean>(
@ -61,14 +61,14 @@ namespace _espe.api
/** /**
*/ */
export const restriction_none : lib_plankton.rest.type_restriction<any> = ( export const restriction_none : lib_plankton.rest_http.type_restriction<any> = (
(stuff) => Promise.resolve<boolean>(true) (stuff) => Promise.resolve<boolean>(true)
); );
/** /**
*/ */
export const restriction_logged_in : lib_plankton.rest.type_restriction<any> = ( export const restriction_logged_in : lib_plankton.rest_http.type_restriction<any> = (
(stuff) => ( (stuff) => (
session_from_stuff(stuff) session_from_stuff(stuff)
.then(() => Promise.resolve<boolean>(true)) .then(() => Promise.resolve<boolean>(true))
@ -82,7 +82,7 @@ namespace _espe.api
export function restriction_verification( export function restriction_verification(
extract_data : ((stuff : type_stuff) => any), extract_data : ((stuff : type_stuff) => any),
extract_verification : ((stuff : type_stuff) => string) extract_verification : ((stuff : type_stuff) => string)
) : lib_plankton.rest.type_restriction<any> ) : lib_plankton.rest_http.type_restriction<any>
{ {
return ( return (
(stuff) => _espe.helpers.verification_check( (stuff) => _espe.helpers.verification_check(
@ -92,17 +92,27 @@ namespace _espe.api
); );
} }
/**
*/
export function full_path(
path : string
) : string
{
return (_espe.conf.get().server.path_base + path);
}
/** /**
*/ */
/*
export function register<type_input, type_output>( export function register<type_input, type_output>(
rest_subject : lib_plankton.rest.type_rest, rest_subject : lib_plankton.rest_http.type_rest,
http_method : lib_plankton.http.enum_method, http_method : lib_plankton.http.enum_method,
path : string, path : string,
options : { options : {
active ?: ((version : string) => boolean); active ?: ((version : (null | string)) => boolean);
restriction ?: (null | lib_plankton.rest.type_restriction<type_input>); restriction ?: (null | lib_plankton.rest_http.type_restriction<type_input>);
execution ?: lib_plankton.rest.type_execution<type_input, type_output>; execution ?: lib_plankton.rest_http.type_execution<type_input, type_output>;
title ?: (null | string); title ?: (null | string);
description ?: (null | string); description ?: (null | string);
query_parameters ?: Array< query_parameters ?: Array<
@ -112,8 +122,8 @@ namespace _espe.api
required : boolean; required : boolean;
} }
>; >;
input_schema ?: ((version: (null | string)) => lib_plankton.rest.type_oas_schema); input_schema ?: ((version: (null | string)) => lib_plankton.rest_http.type_oas_schema);
output_schema ?: ((version: (null | string)) => lib_plankton.rest.type_oas_schema); output_schema ?: ((version: (null | string)) => lib_plankton.rest_http.type_oas_schema);
request_body_mimetype ?: string; request_body_mimetype ?: string;
request_body_decode ?: ((http_request_body : Buffer, http_request_header_content_type : (null | string)) => any); request_body_decode ?: ((http_request_body : Buffer, http_request_header_content_type : (null | string)) => any);
response_body_mimetype ?: string; response_body_mimetype ?: string;
@ -121,17 +131,12 @@ namespace _espe.api
} = {} } = {}
) : void ) : void
{ {
options = Object.assign( lib_plankton.rest_http.register<type_input, type_output>(
{
},
options
);
lib_plankton.rest.register<type_input, type_output>(
rest_subject, rest_subject,
http_method, http_method,
(_espe.conf.get().server.path_base + path), (_espe.conf.get().server.path_base + path),
options options
); );
} }
*/
} }

View file

@ -19,9 +19,9 @@ namespace _espe.api
/** /**
*/ */
export function make( export function make(
) : lib_plankton.rest.type_rest ) : lib_plankton.rest_http.type_rest
{ {
const rest_subject : lib_plankton.rest.type_rest = lib_plankton.rest.make( const rest_subject : lib_plankton.rest_http.type_rest = lib_plankton.rest_http.make(
{ {
"title": "espe", "title": "espe",
"versioning_method": "header", "versioning_method": "header",
@ -29,7 +29,7 @@ namespace _espe.api
"set_access_control_headers": true, "set_access_control_headers": true,
"authentication": { "authentication": {
"kind": "key_header", "kind": "key_header",
"parameters": {"name": "X-Session-Key"} "data": {"name": "X-Session-Key"}
}, },
} }
); );

View file

@ -42,12 +42,7 @@ namespace _espe.conf
/** /**
*/ */
export type type_conf = { export type type_log_channel = (
general : {
language : (null | string);
verification_secret : (null | string);
};
log : Array<
{ {
kind : "stdout"; kind : "stdout";
data : { data : {
@ -77,6 +72,18 @@ namespace _espe.conf
receivers : Array<string>; receivers : Array<string>;
}; };
} }
);
/**
*/
export type type_conf = {
general : {
language : (null | string);
verification_secret : (null | string);
};
log : Array<
type_log_channel
>; >;
server : { server : {
host : string; host : string;

View file

@ -13,27 +13,131 @@ You should have received a copy of the GNU General Public License along with thi
<https://www.gnu.org/licenses/>. <https://www.gnu.org/licenses/>.
*/ */
namespace _espe
/**
*/
async function main(
args_raw : Array<string>
) : Promise<void>
{ {
// init
lib_plankton.log.conf_push( /**
[ */
lib_plankton.log.channel_make( function setup_log_fallback(
) : void
{ {
"kind": "stdout", lib_plankton.log.set_main_logger(
[
{
"kind": "filtered",
"data": { "data": {
"threshold": "notice", "core": {
// "format": "human_readable", "kind": "std",
"data": {
"target": "stdout",
"format": {
"kind": "human_readable",
"data": {}
} }
} }
), },
"predicate": [
[
{
"item": {
"kind": "level",
"data": {"threshold": "info"}
},
}
]
],
}
},
] ]
); );
}
/**
*/
function setup_log_from_conf(
) : void
{
lib_plankton.log.set_main_logger(
_espe.conf.get().log.map(
log_channel => {
switch (log_channel.kind) {
case "stdout": {
return {
"kind": "filtered",
"data": {
"core": {
"kind": "std",
"data": {
"target": "stdout",
"format": {"kind": "human_readable", "data": {}}
}
},
"predicate": [
[
{"item": {"kind": "level", "data": {"threshold": log_channel.data.threshold}}}
]
],
}
};
break;
}
case "file": {
return {
"kind": "filtered",
"data": {
"core": {
"kind": "file",
"data": {
"path": log_channel.data.path,
"format": {"kind": "jsonl", "data": {"structured": false}}
}
},
"predicate": [
[
{"item": {"kind": "level", "data": {"threshold": log_channel.data.threshold}}}
]
],
}
};
break;
}
case "email": {
return {
"kind": "filtered",
"data": {
"core": {
"kind": "email",
"data": log_channel.data
},
"predicate": [
[
{"item": {"kind": "level", "data": {"threshold": log_channel.data.threshold}}}
]
],
}
};
break;
}
default: {
throw (new Error("unhandled log channel"));
break;
}
}
}
)
);
}
/**
*/
export async function main(
args_raw : Array<string>
) : Promise<void>
{
// init
setup_log_fallback();
const language_codes : Array<string> = [ const language_codes : Array<string> = [
"deu", "deu",
"eng", "eng",
@ -198,16 +302,7 @@ async function main(
lib_plankton.translate.promote(language); lib_plankton.translate.promote(language);
} }
} }
lib_plankton.log.conf_push( setup_log_from_conf();
_espe.conf.get().log.map(
log_output => lib_plankton.log.channel_make(
{
"kind": log_output.kind,
"data": log_output.data
}
)
)
);
// exec // exec
if (args["help"] || (args["action"] === "help")) { if (args["help"] || (args["action"] === "help")) {
@ -253,12 +348,12 @@ async function main(
break; break;
} }
case "api-doc": { case "api-doc": {
lib_plankton.log.conf_push([]); // lib_plankton.log.conf_push([]);
const rest_subject : lib_plankton.rest.type_rest = _espe.api.make(); const rest_subject : lib_plankton.rest_http.type_rest = _espe.api.make();
lib_plankton.log.conf_pop(); // lib_plankton.log.conf_pop();
process.stdout.write( process.stdout.write(
JSON.stringify( JSON.stringify(
lib_plankton.rest.to_oas(rest_subject), lib_plankton.rest_http.to_oas(rest_subject),
undefined, undefined,
"\t" "\t"
) )
@ -393,11 +488,11 @@ async function main(
} }
); );
const rest_subject : lib_plankton.rest.type_rest = _espe.api.make(); const rest_subject : lib_plankton.rest_http.type_rest = _espe.api.make();
const server : lib_plankton.server.type_subject = lib_plankton.server.make( const server : lib_plankton.server.type_subject = lib_plankton.server.make(
async (input, metadata) => { async (input, metadata) => {
const http_request : lib_plankton.http.type_request = lib_plankton.http.decode_request(input.toString()); const http_request : lib_plankton.http.type_request = lib_plankton.http.decode_request(input.toString());
const http_response : lib_plankton.http.type_response = await lib_plankton.rest.call( const http_response : lib_plankton.http.type_response = await lib_plankton.rest_http.call(
rest_subject, rest_subject,
http_request, http_request,
{ {
@ -426,11 +521,12 @@ async function main(
} }
} }
} }
}
} }
( (
main(process.argv.slice(2)) _espe.main(process.argv.slice(2))
.then( .then(
() => { () => {
} }

View file

@ -156,7 +156,9 @@ namespace _espe.repository.member
"email_address_private": dispersal.core_row["email_address_private"], "email_address_private": dispersal.core_row["email_address_private"],
"groups": lib_plankton.list.sorted<string>( "groups": lib_plankton.list.sorted<string>(
dispersal.group_rows.map(row => row["group_name"]), dispersal.group_rows.map(row => row["group_name"]),
(group1, group2) => ((group1 <= group2) ? 0 : 1) {
"compare_element": (group1, group2) => (group1 <= group2)
}
), ),
"registered": (dispersal.core_row["registered"] > 0), "registered": (dispersal.core_row["registered"] > 0),
"enabled": (dispersal.core_row["enabled"] > 0), "enabled": (dispersal.core_row["enabled"] > 0),

View file

@ -16,8 +16,8 @@ modules="${modules} storage"
modules="${modules} session" modules="${modules} session"
modules="${modules} json" modules="${modules} json"
modules="${modules} api" modules="${modules} api"
modules="${modules} rest"
modules="${modules} http" modules="${modules} http"
modules="${modules} rest_http"
modules="${modules} server" modules="${modules} server"
modules="${modules} email" modules="${modules} email"
modules="${modules} args" modules="${modules} args"