From b86e1b62e28b2bbebce4d3c97db3fb495a3a6f4e Mon Sep 17 00:00:00 2001 From: Fenris Wolf Date: Thu, 28 Nov 2024 23:06:57 +0100 Subject: [PATCH] [upd] plankton --- lib/plankton/plankton.d.ts | 242 +++++------- lib/plankton/plankton.js | 785 ++++++++++++++++++++++--------------- 2 files changed, 571 insertions(+), 456 deletions(-) diff --git a/lib/plankton/plankton.d.ts b/lib/plankton/plankton.d.ts index 355d916..42b9f20 100644 --- a/lib/plankton/plankton.d.ts +++ b/lib/plankton/plankton.d.ts @@ -1588,7 +1588,7 @@ declare namespace lib_plankton.string { * @return {Array} * @author fenris */ - function split(chain: string, separator?: string): Array; + function split(chain: string, separator: string): Array; /** * @author neu3no */ @@ -3651,60 +3651,38 @@ declare namespace lib_plankton.http { declare namespace lib_plankton.xml { /** */ - abstract class class_node { - /** - */ - abstract compile(depth?: int): string; - } - /** - */ - class class_node_text extends class_node { - /** - */ - protected content: string; - /** - */ - constructor(content: string); - /** - */ - compile(depth?: int): string; - } - /** - */ - class class_node_comment extends class_node { - /** - */ - protected content: string; - /** - */ - constructor(content: string); - /** - */ - compile(depth?: int): string; - } - /** - */ - class class_node_complex extends class_node { - /** - */ - protected name: string; - /** - */ - protected attributes: { - [key: string]: string; + type type_node_data = ({ + kind: "root"; + data: { + version: string; + encoding: string; + content: type_node_data; }; - /** - */ - protected children: Array; - /** - */ - constructor(name: string, attributes?: { - [key: string]: string; - }, children?: any[]); - /** - */ - compile(depth?: int): string; - } + } | { + kind: "comment"; + data: string; + } | { + kind: "text"; + data: string; + } | { + kind: "complex"; + data: { + tag: string; + attributes: Record; + children: Array; + }; + }); + /** + */ + type type_node_logic = { + compile: ((depths: int) => string); + }; + /** + */ + function get_node_logic(node_data: type_node_data): type_node_logic; + /** + */ + function parse(xml_string: string): Promise; } declare namespace lib_plankton.webdav { /** @@ -3794,12 +3772,33 @@ declare namespace lib_plankton.webdav { * @see http://www.webdav.org/specs/rfc2518.html#ELEMENT_status */ type type_data_status = string; + /** + */ + type type_data_prop_value = ({ + kind: "none"; + data: null; + } | { + kind: "primitive"; + data: string; + } | { + kind: "href"; + data: string; + } | { + kind: "resourcetype"; + data: { + kind: string; + type: string; + }; + } | { + kind: "privileges"; + data: Array; + }); /** * @see http://www.webdav.org/specs/rfc2518.html#ELEMENT_prop */ type type_data_prop = { name: string; - value: (null | string); + value: type_data_prop_value; }; /** * @see http://www.webdav.org/specs/rfc2518.html#ELEMENT_propstat @@ -3838,7 +3837,6 @@ declare namespace lib_plankton.webdav { } declare namespace lib_plankton.webdav { /** - * @author roydfalk */ function is_special_method(method: enum_method): boolean; /** @@ -3865,6 +3863,10 @@ declare namespace lib_plankton.webdav { /** */ function encode_request(request: type_request): string; + /** + * @todo description + */ + function data_multistatus_encode_xml(data_multistatus: type_data_multistatus): lib_plankton.xml.type_node_data; /** */ function data_multistatus_encode(data_multistatus: type_data_multistatus): string; @@ -4165,7 +4167,6 @@ declare namespace lib_plankton.rest_base { /** */ type type_execution = ((stuff: { - version: (null | string); headers: Record; path_parameters: Record; query_parameters: Record; @@ -4178,7 +4179,6 @@ declare namespace lib_plankton.rest_base { /** */ type type_restriction = ((stuff: { - version: (null | string); headers: Record; path_parameters: Record; query_parameters: Record; @@ -4187,22 +4187,22 @@ declare namespace lib_plankton.rest_base { */ type type_operation = { action_name: string; - query_parameters: ((version: string) => Array<{ + query_parameters: ((version: (null | string)) => Array<{ name: string; description: (null | string); required: boolean; }>); input_schema: ((version: (null | string)) => type_oas_schema); output_schema: ((version: (null | string)) => type_oas_schema); - request_body_mimetype: string; - request_body_decode: ((http_request_body: Buffer, http_request_header_content_type: (null | string)) => any); - response_body_mimetype: string; - response_body_encode: ((output: any) => (null | Buffer)); + request_body_mimetype: ((version: (null | string)) => string); + request_body_decode: ((version: (null | string)) => (http_request_body: Buffer, http_request_header_content_type: (null | string)) => any); + response_body_mimetype: ((version: (null | string)) => string); + response_body_encode: ((version: (null | string)) => ((output: any) => (null | Buffer))); }; /** */ type type_routenode = { - operations: Record>; + operations: Record>; sub_branch: Record; sub_wildcard: (null | { name: string; @@ -4225,19 +4225,39 @@ declare namespace lib_plankton.rest_base { set_access_control_headers: boolean; authentication: ({ kind: "none"; - parameters: {}; + data: {}; } | { kind: "key_header"; - parameters: { + data: { name: string; }; }); }; + /** + */ + type type_action_options = { + active?: ((version: (null | string)) => boolean); + restriction?: ((version: (null | string)) => type_restriction); + execution?: ((version: (null | string)) => type_execution); + title?: ((version: (null | string)) => (null | string)); + description?: ((version: (null | string)) => (null | string)); + query_parameters?: ((version: (null | string)) => Array<{ + name: string; + description: (null | string); + required: boolean; + }>); + input_schema?: ((version: (null | string)) => type_oas_schema); + output_schema?: ((version: (null | string)) => type_oas_schema); + request_body_mimetype?: ((version: (null | string)) => string); + request_body_decode?: ((version: (null | string)) => (http_request_body: Buffer, http_request_header_content_type: (null | string)) => Promise); + response_body_mimetype?: ((version: (null | string)) => string); + response_body_encode?: ((version: (null | string)) => (output: any) => Promise); + }; } declare namespace lib_plankton.rest_base { /** */ - function make(encode_http_method: ((http_method: type_http_method) => string), options?: { + function make(encode_http_method: ((http_method: type_http_method) => string), { "title": option_title, "versioning_method": option_versioning_method, "versioning_header_name": option_versioning_header_name, "versioning_query_key": option_versioning_query_key, "header_parameters": option_header_parameters, "set_access_control_headers": option_set_access_control_headers, "authentication": option_authentication, "actions": option_actions, }?: { title?: (null | string); versioning_method?: ("none" | "path" | "header" | "query"); versioning_header_name?: (null | string); @@ -4250,56 +4270,26 @@ declare namespace lib_plankton.rest_base { set_access_control_headers?: boolean; authentication?: ({ kind: "none"; - parameters: {}; + data: {}; } | { kind: "key_header"; - parameters: { + data: { name: string; }; }); actions?: Array<{ http_method: type_http_method; path: string; - options: { - active?: ((version: string) => boolean); - restriction?: (null | type_restriction); - execution?: type_execution; - title?: (null | string); - description?: (null | string); - query_parameters?: ((version: string) => Array<{ - name: string; - description: (null | string); - required: boolean; - }>); - input_schema?: ((version: string) => type_oas_schema); - output_schema?: ((version: string) => type_oas_schema); - request_body_mimetype?: string; - request_body_decode?: ((http_request_body: Buffer, http_request_header_content_type: (null | string)) => any); - response_body_mimetype?: string; - response_body_encode?: ((output: any) => Buffer); - }; + options: type_action_options; }>; }): type_rest; /** */ - function register(encode_http_method: ((http_method: type_http_method) => string), rest: type_rest, http_method: type_http_method, path: string, options: { - active?: ((version: string) => boolean); - restriction?: (null | type_restriction); - execution?: type_execution; - title?: (null | string); - description?: (null | string); - query_parameters?: ((version: string) => Array<{ - name: string; - description: (null | string); - required: boolean; - }>); - input_schema?: ((version: (null | string)) => type_oas_schema); - output_schema?: ((version: (null | string)) => type_oas_schema); - request_body_mimetype?: string; - request_body_decode?: ((http_request_body: Buffer, http_request_header_content_type: (null | string)) => any); - response_body_mimetype?: string; - response_body_encode?: ((output: any) => Buffer); - }): void; + function register(encode_http_method: ((http_method: type_http_method) => string), rest: type_rest, http_method: type_http_method, path: string, { "active": option_active, "execution": option_execution, "restriction": option_restriction, "title": option_title, "description": option_description, "query_parameters": option_query_parameters, "input_schema": option_input_schema, "output_schema": option_output_schema, "request_body_mimetype": option_request_body_mimetype, "request_body_decode": option_request_body_decode, "response_body_mimetype": option_response_body_mimetype, + /** + * @todo no "from"? + */ + "response_body_encode": option_response_body_encode, }?: type_action_options): void; /** * @todo check request body mimetype? * @todo check query paramater validity @@ -4354,56 +4344,22 @@ declare namespace lib_plankton.rest_caldav { set_access_control_headers?: boolean; authentication?: ({ kind: "none"; - parameters: {}; + data: {}; } | { kind: "key_header"; - parameters: { + data: { name: string; }; }); actions?: Array<{ http_method: lib_plankton.caldav.enum_method; path: string; - options: { - active?: ((version: string) => boolean); - restriction?: (null | type_restriction); - execution?: type_execution; - title?: (null | string); - description?: (null | string); - query_parameters?: ((version: string) => Array<{ - name: string; - description: (null | string); - required: boolean; - }>); - input_schema?: ((version: string) => type_oas_schema); - output_schema?: ((version: string) => type_oas_schema); - request_body_mimetype?: string; - request_body_decode?: ((http_request_body: Buffer, http_request_header_content_type: (null | string)) => any); - response_body_mimetype?: string; - response_body_encode?: ((output: any) => Buffer); - }; + options: lib_plankton.rest_base.type_action_options; }>; }): type_rest; /** */ - function register(rest: type_rest, http_method: lib_plankton.caldav.enum_method, path: string, options: { - active?: ((version: string) => boolean); - restriction?: (null | type_restriction); - execution?: type_execution; - title?: (null | string); - description?: (null | string); - query_parameters?: ((version: string) => Array<{ - name: string; - description: (null | string); - required: boolean; - }>); - input_schema?: ((version: (null | string)) => type_oas_schema); - output_schema?: ((version: (null | string)) => type_oas_schema); - request_body_mimetype?: string; - request_body_decode?: ((http_request_body: Buffer, http_request_header_content_type: (null | string)) => any); - response_body_mimetype?: string; - response_body_encode?: ((output: any) => Buffer); - }): void; + function register(rest: type_rest, http_method: lib_plankton.caldav.enum_method, path: string, options: lib_plankton.rest_base.type_action_options): void; /** * @todo check request body mimetype? * @todo check query paramater validity diff --git a/lib/plankton/plankton.js b/lib/plankton/plankton.js index c5cc5ee..865d6e3 100644 --- a/lib/plankton/plankton.js +++ b/lib/plankton/plankton.js @@ -4517,7 +4517,7 @@ var lib_plankton; .map((report_entry) => ({ "incident": report_entry.incident, "details": Object.assign(report_entry.details, { - "path": (report_entry.details.path ?? []).concat([entry.right]) + "path": [entry.right].concat(report_entry.details.path ?? []), }), }))); } @@ -4548,7 +4548,7 @@ var lib_plankton; .map((report_entry) => ({ "incident": report_entry.incident, "details": Object.assign(report_entry.details, { - "path": (report_entry.details.path ?? []).concat([entry.left]) + "path": [entry.left].concat(report_entry.details.path ?? []), }), }))); } @@ -4566,7 +4566,7 @@ var lib_plankton; .map((report_entry) => ({ "incident": report_entry.incident, "details": Object.assign(report_entry.details, { - "path": (report_entry.details.path ?? []).concat([entry.right]) + "path": [entry.right].concat(report_entry.details.path ?? []), }), }))); } @@ -4864,7 +4864,7 @@ var lib_plankton; * @return {Array} * @author fenris */ - function split(chain, separator = " ") { + function split(chain, separator) { if (chain.length == 0) { return []; } @@ -12362,44 +12362,49 @@ var lib_plankton; /** */ function decode_request(decode_method, has_body, request_raw) { - const lines = request_raw.split(linebreak); - const first = lines[0]; - lines.shift(); - const parts = first.split(" "); - const method = decode_method(parts[0]); - const path_and_query = parts[1]; - const parts_ = path_and_query.split("?"); - const path = parts_[0]; - const query = ((parts_.length <= 1) ? null : ("?" + parts_.slice(1).join("?"))); - const version = parts[2]; - let headers = {}; - while (true) { - const line = lines[0]; - lines.shift(); - if (line === "") { - break; - } - else { - const [key, value] = line.split(": ", 2); - headers[key.toLowerCase()] = value; - } + const lines = lib_plankton.string.split(request_raw, linebreak); + if (lines.length <= 0) { + throw (new Error("malformed request")); + } + else { + const first = lines[0]; + lines.shift(); + const parts = first.split(" "); + const method = decode_method(parts[0]); + const path_and_query = parts[1]; + const parts_ = path_and_query.split("?"); + const path = parts_[0]; + const query = ((parts_.length <= 1) ? null : ("?" + parts_.slice(1).join("?"))); + const version = parts[2]; + let headers = {}; + while (true) { + const line = lines[0]; + lines.shift(); + if (line === "") { + break; + } + else { + const [key, value] = line.split(": ", 2); + headers[key.toLowerCase()] = value; + } + } + const body = (has_body(method) + // @ts-ignore + ? Buffer.from(lines.join(linebreak)) + : null); + const request = { + // TODO + "scheme": "http", + "host": (headers["host"] ?? null), + "path": path, + "version": version, + "method": method, + "query": query, + "headers": headers, + "body": body, + }; + return request; } - const body = (has_body(method) - // @ts-ignore - ? Buffer.from(lines.join(linebreak)) - : null); - const request = { - // TODO - "scheme": "http", - "host": (headers["host"] ?? null), - "path": path, - "version": version, - "method": method, - "query": query, - "headers": headers, - "body": body, - }; - return request; } http_base.decode_request = decode_request; /** @@ -12878,21 +12883,6 @@ var lib_plankton; http.call = call; })(http = lib_plankton.http || (lib_plankton.http = {})); })(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:xml«. @@ -12923,100 +12913,162 @@ var lib_plankton; } /** */ - var class_node = /** @class */ (function () { - function class_node() { - } - return class_node; - }()); - xml.class_node = class_node; + function get_node_logic(node_data) { + return lib_plankton.call.distinguish(node_data, { + "root": function (_a) { + var version = _a["version"], encoding = _a["encoding"], content = _a["content"]; + return ({ + "compile": function (depth) { return (("") + + + "\n" + + + get_node_logic(content).compile(depth)); } + }); + }, + "comment": function (content) { return ({ + "compile": function (depth) { return (string_repeat("\t", depth) + + + content); } + }); }, + "text": function (content) { return ({ + "compile": function (depth) { return (string_repeat("\t", depth) + + + content); } + }); }, + "complex": function (_a) { + var tag = _a["tag"], attributes = _a["attributes"], children = _a["children"]; + return ({ + "compile": function (depth) { + var output = ""; + var attributes_string = (Object.keys(attributes) + .filter(function (key) { return (attributes[key] !== null); }) + .map(function (key) { return (" " + key + "=" + ("\"" + attributes[key] + "\"")); }) + .join("")); + if (children.length === 0) { + output += (string_repeat("\t", depth) + + + ("<" + tag + attributes_string + "/>") + + + "\n"); + } + else if ((children.length === 1) + && + (children[0].kind === "text")) { + output += (string_repeat("\t", depth) + + + ("<" + tag + attributes_string + ">") + + + get_node_logic(children[0]).compile(0) + + + ("") + + + "\n"); + } + else { + output += (string_repeat("\t", depth) + + + ("<" + tag + attributes_string + ">") + + + "\n"); + for (var _i = 0, children_1 = children; _i < children_1.length; _i++) { + var child = children_1[_i]; + output += get_node_logic(child).compile(depth + 1); + } + output += (string_repeat("\t", depth) + + + ("") + + + "\n"); + } + return output; + } + }); + } + }); + } + xml.get_node_logic = get_node_logic; /** */ - var class_node_text = /** @class */ (function (_super) { - __extends(class_node_text, _super); - /** - */ - function class_node_text(content) { - var _this = _super.call(this) || this; - _this.content = content; - return _this; + function convert_xml2js_data_to_node(is_root, tag, xml2js_data) { + if (typeof (xml2js_data) === "string") { + return ((tag === null) + ? + { + "kind": "text", + "data": xml2js_data + } + : + { + "kind": "complex", + "data": { + "tag": tag, + "attributes": {}, + "children": ((xml2js_data === "") + ? + [] + : + [ + { + "kind": "text", + "data": xml2js_data + } + ]) + } + }); } - /** - */ - class_node_text.prototype.compile = function (depth) { - if (depth === void 0) { depth = 0; } - return (string_repeat("\t", depth) + this.content /* + "\n"*/); - }; - return class_node_text; - }(class_node)); - xml.class_node_text = class_node_text; - /** - */ - var class_node_comment = /** @class */ (function (_super) { - __extends(class_node_comment, _super); - /** - */ - function class_node_comment(content) { - var _this = _super.call(this) || this; - _this.content = content; - return _this; - } - /** - */ - class_node_comment.prototype.compile = function (depth) { - if (depth === void 0) { depth = 0; } - return (string_repeat("\t", depth) + "" + "\n"); - }; - return class_node_comment; - }(class_node)); - xml.class_node_comment = class_node_comment; - /** - */ - var class_node_complex = /** @class */ (function (_super) { - __extends(class_node_complex, _super); - /** - */ - function class_node_complex(name, attributes, children) { - if (attributes === void 0) { attributes = {}; } - if (children === void 0) { children = []; } - var _this = _super.call(this) || this; - _this.name = name; - _this.attributes = attributes; - _this.children = children; - return _this; - } - /** - */ - class_node_complex.prototype.compile = function (depth) { - var _this = this; - if (depth === void 0) { depth = 0; } - var output = ""; - var attributes = (Object.keys(this.attributes) - .filter(function (key) { return (_this.attributes[key] !== null); }) - .map(function (key) { return (" " + key + "=" + ("\"" + _this.attributes[key] + "\"")); }) - .join("")); - if ((this.children.length === 1) - && - (this.children[0] instanceof class_node_text)) { - output += (string_repeat("\t", depth) - + - ("<" + this.name + attributes + ">") - + - this.children[0].compile(0) - + - ("") - + - "\n"); + else { + if (tag === null) { + throw (new Error("tag required")); } else { - output += (string_repeat("\t", depth) + "<" + this.name + attributes + ">" + "\n"); - this.children.forEach(function (child) { return (output += child.compile(depth + 1)); }); - output += (string_repeat("\t", depth) + "" + "\n"); + var attributes = {}; + var children = []; + for (var _i = 0, _a = Object.entries(xml2js_data); _i < _a.length; _i++) { + var _b = _a[_i], key = _b[0], value = _b[1]; + if (key === "$") { + attributes = value; + } + else { + if (value instanceof Array) { + for (var _c = 0, _d = value; _c < _d.length; _c++) { + var sub = _d[_c]; + children.push(convert_xml2js_data_to_node(false, key, sub)); + } + } + else { + children.push(convert_xml2js_data_to_node(false, key, value)); + } + } + } + if (is_root + && + (Object.keys(attributes).length === 0) + && + (children.length === 1)) { + return children[0]; + } + else { + return { + "kind": "complex", + "data": { + "tag": tag, + "attributes": attributes, + "children": children + } + }; + } } - return output; - }; - return class_node_complex; - }(class_node)); - xml.class_node_complex = class_node_complex; + } + } + /** + */ + function parse(xml_string) { + var nm_xml2js = require("xml2js"); + return (nm_xml2js.parseStringPromise(xml_string) + .then(function (data_raw) { return Promise.resolve(data_raw); }) + .then(function (xml2js_data) { return Promise.resolve(convert_xml2js_data_to_node(true, "_", xml2js_data)); })); + } + xml.parse = parse; })(xml = lib_plankton.xml || (lib_plankton.xml = {})); })(lib_plankton || (lib_plankton = {})); /* @@ -13150,7 +13202,6 @@ var lib_plankton; var webdav; (function (webdav) { /** - * @author roydfalk */ function is_special_method(method) { return ((method === webdav.enum_method.propfind) @@ -13210,7 +13261,7 @@ var lib_plankton; case "MOVE": return webdav.enum_method.move; case "LOCK": return webdav.enum_method.lock; case "UNLOCK": return webdav.enum_method.unlock; - default: throw (new Error("unhandled method: " + method_raw)); + default: throw (new Error("unhandled methoD: " + method_raw)); } } webdav.decode_method = decode_method; @@ -13331,67 +13382,177 @@ var lib_plankton; /** */ function data_href_encode_xml(data_href) { - return (new lib_plankton.xml.class_node_complex("D:href", {}, [ - new lib_plankton.xml.class_node_text(data_href), - ])); + return { + "kind": "complex", + "data": { + "tag": "D:href", + "attributes": {}, + "children": [ + { + "kind": "text", + "data": data_href, + }, + ] + } + }; } /** */ function data_status_encode_xml(data_status) { - return (new lib_plankton.xml.class_node_complex("D:status", {}, [ - new lib_plankton.xml.class_node_text(data_status), - ])); + return { + "kind": "complex", + "data": { + "tag": "D:status", + "attributes": {}, + "children": [ + { + "kind": "text", + "data": data_status, + }, + ] + } + }; } /** */ function data_prop_encode_xml(data_prop) { - return (new lib_plankton.xml.class_node_complex(("D:" + data_prop.name), {}, [ - new lib_plankton.xml.class_node_text(data_prop.value - ?? - ""), - ])); + return { + "kind": "complex", + "data": { + "tag": data_prop.name, + "attributes": {}, + "children": lib_plankton.call.distinguish(data_prop.value, { + "none": () => ([]), + "primitive": (content) => ([ + { + "kind": "text", + "data": content + }, + ]), + "href": (url) => ([ + { + "kind": "complex", + "data": { + "tag": "D:href", + "attributes": {}, + "children": [ + { + "kind": "text", + "data": url + } + ] + } + }, + ]), + "resourcetype": ({ "kind": kind, "type": type }) => ([ + { + "kind": "complex", + "data": { + "tag": ("D:" + kind), + "attributes": {}, + "children": [] + } + }, + { + "kind": "complex", + "data": { + "tag": ("C:" + type), + "attributes": {}, + "children": [] + } + }, + ]), + "privileges": (items) => ([ + { + "kind": "complex", + "data": { + "tag": "D:privilege", + "attributes": {}, + "children": items.map(item => ({ + "kind": "complex", + "data": { + "tag": ("D:" + item), + "attributes": {}, + "children": [] + } + })) + } + }, + ]), + }) + } + }; } /** */ function data_propstat_encode_xml(data_propstat) { - return (new lib_plankton.xml.class_node_complex("D:propstat", { - // todo xmlns:R - }, [ - new lib_plankton.xml.class_node_complex("D:prop", { - // todo xmlns:R - }, data_propstat.prop.map(data_prop_encode_xml)), - data_status_encode_xml(data_propstat.status), - ])); + return { + "kind": "complex", + "data": { + "tag": "D:propstat", + "attributes": { + // todo xmlns:R + }, + "children": [ + { + "kind": "complex", + "data": { + "tag": "D:prop", + "attributes": { + // todo xmlns:R + }, + "children": data_propstat.prop.map(data_prop_encode_xml), + }, + }, + data_status_encode_xml(data_propstat.status), + ] + } + }; } /** */ function data_response_encode_xml(data_response) { - return (new lib_plankton.xml.class_node_complex("D:response", {}, ([ - data_href_encode_xml(data_response.href), - ] - .concat(("hrefs" in data_response.body) - ? - (data_response.body.hrefs.map(data_href_encode_xml) - .concat([ - data_status_encode_xml(data_response.body.status), - ])) - : - data_response.body.propstats.map(data_propstat_encode_xml))))); + return { + "kind": "complex", + "data": { + "tag": "D:response", + "attributes": {}, + "children": ([ + data_href_encode_xml(data_response.href), + ] + .concat(("hrefs" in data_response.body) + ? + (data_response.body.hrefs.map(data_href_encode_xml) + .concat([ + data_status_encode_xml(data_response.body.status), + ])) + : + data_response.body.propstats.map(data_propstat_encode_xml))) + } + }; } /** * @todo description */ function data_multistatus_encode_xml(data_multistatus) { - return (new lib_plankton.xml.class_node_complex("D:multistatus", { - "xmlns:D": "DAV:", - "xmlns:C": "urn:ietf:params:xml:ns:caldav", - "xmlns:CS": "http://calendarserver.org/ns/", - }, data_multistatus.responses.map(data_response_encode_xml))); + return { + "kind": "complex", + "data": { + "tag": "D:multistatus", + "attributes": { + "xmlns:D": "DAV:", + "xmlns:C": "urn:ietf:params:xml:ns:caldav", + "xmlns:CS": "http://calendarserver.org/ns/", + }, + "children": data_multistatus.responses.map(data_response_encode_xml), + } + }; } + webdav.data_multistatus_encode_xml = data_multistatus_encode_xml; /** */ function data_multistatus_encode(data_multistatus) { - return data_multistatus_encode_xml(data_multistatus).compile(); + return lib_plankton.xml.get_node_logic(data_multistatus_encode_xml(data_multistatus)).compile(0); } webdav.data_multistatus_encode = data_multistatus_encode; })(webdav = lib_plankton.webdav || (lib_plankton.webdav = {})); @@ -14122,6 +14283,7 @@ var lib_plankton; api.class_api = class_api; })(api = lib_plankton.api || (lib_plankton.api = {})); })(lib_plankton || (lib_plankton = {})); +"use strict"; /* This file is part of »bacterio-plankton:rest_base«. @@ -14362,35 +14524,25 @@ var lib_plankton; } /** */ - function make(encode_http_method, options = {}) { - options = lib_plankton.object.patched({ - "title": "REST-API", - "versioning_method": "none", - "versioning_header_name": "X-Api-Version", - "versioning_query_key": "version", - "header_parameters": [], - "set_access_control_headers": false, - "authentication": { - "kind": "none", - "parameters": {}, - }, - "actions": [], - }, options); + function make(encode_http_method, { "title": option_title = "REST-API", "versioning_method": option_versioning_method = "none", "versioning_header_name": option_versioning_header_name = "X-Api-Version", "versioning_query_key": option_versioning_query_key = "version", "header_parameters": option_header_parameters = [], "set_access_control_headers": option_set_access_control_headers = false, "authentication": option_authentication = { + "kind": "none", + "data": {}, + }, "actions": option_actions = [], } = {}) { const subject = { - "api": lib_plankton.api.make(options.title), - "versioning_method": options.versioning_method, - "versioning_header_name": options.versioning_header_name, - "versioning_query_key": options.versioning_query_key, + "api": lib_plankton.api.make(option_title ?? ""), + "versioning_method": option_versioning_method, + "versioning_header_name": option_versioning_header_name, + "versioning_query_key": option_versioning_query_key, "routetree": { "operations": {}, "sub_branch": {}, "sub_wildcard": null, }, - "header_parameters": options.header_parameters, - "set_access_control_headers": options.set_access_control_headers, - "authentication": options.authentication, + "header_parameters": option_header_parameters, + "set_access_control_headers": option_set_access_control_headers, + "authentication": option_authentication, }; - options.actions.forEach((action_definition) => { + option_actions.forEach((action_definition) => { register(encode_http_method, subject, action_definition.http_method, action_definition.path, action_definition.options); }); return subject; @@ -14398,74 +14550,71 @@ var lib_plankton; rest_base.make = make; /** */ - function register(encode_http_method, rest, http_method, path, options) { - options = lib_plankton.object.patched({ - "active": ((version) => true), - "execution": ((stuff) => Promise.resolve({ "status_code": 501, "data": null })), - "restriction": ((stuff) => Promise.resolve(true)), - "title": null, - "description": null, - "query_parameters": ((version) => ([])), - "input_schema": ((version) => ({})), - "output_schema": ((version) => ({})), - "request_body_mimetype": "application/json", - "request_body_decode": ((http_request_body, http_request_header_content_type) => (((http_request_header_content_type !== null) - && - (http_request_header_content_type.startsWith("application/json")) - && - (http_request_body !== null) - && - (http_request_body.toString() !== "")) - ? JSON.parse(http_request_body.toString()) - : ((http_request_body !== null) - ? http_request_body.toString() - : null))), - "response_body_mimetype": "application/json", - /** - * @todo no "from"? - */ - "response_body_encode": ((output) => Buffer["from"](JSON.stringify(output))), - }, options); + function register(encode_http_method, rest, http_method, path, { "active": option_active = (version) => true, "execution": option_execution = (version) => (stuff) => Promise.resolve({ "status_code": 501, "data": null }), "restriction": option_restriction = (version) => (stuff) => Promise.resolve(true), "title": option_title = (version) => null, "description": option_description = (version) => null, "query_parameters": option_query_parameters = (version) => ([]), "input_schema": option_input_schema = (version) => ({}), "output_schema": option_output_schema = (version) => ({}), "request_body_mimetype": option_request_body_mimetype = (version) => "application/json", "request_body_decode": option_request_body_decode = (version) => (http_request_body, http_request_header_content_type) => Promise.resolve(((http_request_header_content_type !== null) + && + (http_request_header_content_type.startsWith("application/json")) + && + (http_request_body !== null) + && + (http_request_body.toString() !== "")) + ? + JSON.parse(http_request_body.toString()) + : + ((http_request_body !== null) + ? + http_request_body.toString() + : + null)), "response_body_mimetype": option_response_body_mimetype = (version) => "application/json", + /** + * @todo no "from"? + */ + "response_body_encode": option_response_body_encode = (version) => (output) => Promise.resolve(Buffer["from"](JSON.stringify(output))), } = {}) { const steps = lib_plankton.string.split(path, "/").slice(1); const steps_enriched = ((rest.versioning_method === "path") - ? ["{version}"].concat(steps) - : steps); + ? + ["{version}"].concat(steps) + : + steps); const http_method_encoded = encode_http_method(http_method).toLowerCase(); const action_name = (steps.concat([http_method_encoded]) .join("_")); const operation = { "action_name": action_name, - "query_parameters": options.query_parameters, - "request_body_mimetype": options.request_body_mimetype, - "request_body_decode": options.request_body_decode, - "response_body_mimetype": options.response_body_mimetype, - "response_body_encode": options.response_body_encode, - "input_schema": options.input_schema, - "output_schema": options.output_schema, + "query_parameters": option_query_parameters, + "request_body_mimetype": option_request_body_mimetype, + "request_body_decode": option_request_body_decode, + "response_body_mimetype": option_response_body_mimetype, + "response_body_encode": option_response_body_encode, + "input_schema": option_input_schema, + "output_schema": option_output_schema, }; routenode_path_write(encode_http_method, rest.routetree, steps_enriched, http_method, operation, { "create": true, }); lib_plankton.api.register(rest.api, action_name, { - "active": options.active, - "execution": (version, environment, input) => options.execution({ - "version": version, + "active": option_active, + "execution": (version, environment, input) => option_execution(version)({ "path_parameters": environment.path_parameters, "query_parameters": environment.query_parameters, "headers": environment.headers, "input": input }), - "restriction": (version, environment) => options.restriction({ - "version": version, + "restriction": (version, environment) => option_restriction(version)({ "path_parameters": environment.path_parameters, "query_parameters": environment.query_parameters, "headers": environment.headers, }), - "title": options.title, - "description": options.description, + /** + * @todo heed version + */ + "title": option_title(null), + /** + * @todo heed version + */ + "description": option_description(null), // TODO - // "input_shape": options.input_type, - // "output_shape": options.output_type, + // "input_shape": option_input_type, + // "output_shape": option_output_type, }); lib_plankton.log.debug("plankton.rest_base.route_added", { "http_method": http_method, @@ -14492,13 +14641,13 @@ var lib_plankton; null : lib_plankton.string.limit(http_request.body.toString(), { - "length": 200, + "length": 2047, })), }); // parse target and query parameters // const url_stuff : URL = new URL("http://dummy" + http_request.target); const path = http_request.path; - const query_parameters_raw = new URLSearchParams(http_request.query); + const query_parameters_raw = new URLSearchParams(http_request.query ?? ""); let query_parameters = {}; for (const [key, value] of query_parameters_raw) { query_parameters[key] = value; @@ -14526,13 +14675,23 @@ var lib_plankton; break; } case "header": { - version = http_request.headers[rest.versioning_header_name]; - // delete http_request.headers[rest.versioning_header_name]; + if (rest.versioning_header_name === null) { + throw (new Error("versioning_header_name not set")); + } + else { + version = http_request.headers[rest.versioning_header_name]; + // delete http_request.headers[rest.versioning_header_name]; + } break; } case "query": { - version = query_parameters[rest.versioning_query_key]; - // delete query_parameters[rest.versioning_query_key]; + if (rest.versioning_query_key === null) { + throw (new Error("versioning_query_key not set")); + } + else { + version = query_parameters[rest.versioning_query_key]; + // delete query_parameters[rest.versioning_query_key]; + } break; } default: { @@ -14542,29 +14701,19 @@ var lib_plankton; } const additional_response_headers = (rest.set_access_control_headers ? { - /* - "Access-Control-Allow-Headers": ( - ( - [ - "Content-Type", - "X-Api-Key", - ] - .concat( - (rest.versioning_header_name !== null) - ? [rest.versioning_header_name] - : [] - ) - .concat( - (rest.authentication.kind === "key_header") - ? [rest.authentication.parameters["name"]] - : [] - ) - ) - .join(", ") - ), - */ + "Access-Control-Allow-Headers": (([ + "Content-Type", + "X-Api-Key", + ] + .concat((rest.versioning_header_name !== null) + ? [rest.versioning_header_name] + : []) + .concat((rest.authentication.kind === "key_header") + ? [rest.authentication.data["name"]] + : [])) + .join(", ")), "Access-Control-Allow-Origin": "*", - // "Access-Control-Allow-Methods": allowed_methods, + "Access-Control-Allow-Methods": allowed_methods, } : {}); let response; @@ -14633,12 +14782,14 @@ var lib_plankton; "path_parameters": stuff.parameters, "query_parameters": query_parameters, "input": ((http_request.body === null) - ? null - : operation.request_body_decode(http_request.body, (http_request.headers["Content-Type"] - ?? - http_request.headers["content-type"] - ?? - null))), + ? + null + : + await operation.request_body_decode(version)(http_request.body, (http_request.headers["Content-Type"] + ?? + http_request.headers["content-type"] + ?? + null))), }; /*const allowed : boolean = ( (operation.restriction === null) @@ -14662,7 +14813,7 @@ var lib_plankton; lib_plankton.string.limit( http_request.body.toString(), { - "length": 200, + "length": 2047, } ) ), @@ -14716,7 +14867,7 @@ var lib_plankton; null : lib_plankton.string.limit(http_request.body.toString(), { - "length": 200 + "length": 2047 })), }, "error": ((error === null) @@ -14741,21 +14892,21 @@ var lib_plankton; } else { // encode - const body = operation.response_body_encode(result.data); + const body = await operation.response_body_encode(version)(result.data); response = { "version": http_request.version, "status_code": decode_status_code(result.status_code), "headers": Object.assign({}, additional_response_headers, ((body !== null) ? { - "Content-Type": operation.response_body_mimetype, + "Content-Type": operation.response_body_mimetype(version), } : {}), ((option_set_content_length && (body !== null)) ? - // @ts-ignore + // @ts-ignore Buffer HAS a length { "Content-Length": body.length } : {}), (result.extra_headers ?? {})), @@ -14775,7 +14926,7 @@ var lib_plankton; null : lib_plankton.string.limit(response.body.toString(), { - "length": 200, + "length": 2047, })), }); return response; @@ -14797,16 +14948,16 @@ var lib_plankton; }, "servers": option_servers.map(url => ({ "url": url })), "components": { - "securitySchemes": (((description) => ({ - "none": {}, - "key_header": { + "securitySchemes": lib_plankton.call.distinguish(rest.authentication, { + "none": ({}) => ({}), + "key_header": ({ "name": name }) => ({ "default_security_schema": { "type": "restKey", "in": "header", - "name": description.parameters["name"], + "name": name, }, - }, - }[description.kind]))(rest.authentication)), + }), + }), }, "security": [ { @@ -14827,24 +14978,31 @@ var lib_plankton; return [ key, lib_plankton.call.convey(entry.node.operations, [ - x => Object.entries(x), + (x) => Object.entries(x), (pairs) => pairs.map(([http_method, operation]) => ([ + /** + * @todo rectify type argument + */ http_request_method_to_oas(http_method), { + /** + * @todo rectify type argument + */ "operationId": (http_request_method_to_oas(http_method) + "_" + path), - "summary": (operation.title + "summary": (operation.action_name ?? [""].concat(steps_).join(" ")), "description": (lib_plankton.api.get_action(rest.api, operation.action_name).description ?? "(missing)"), - "parameters": [].concat( - // header parameters - rest.header_parameters.map(header_parameter => ({ + "parameters": ((new Array()) + // header parameters + .concat(rest.header_parameters + .map(header_parameter => ({ "name": header_parameter.name, "in": "header", "required": header_parameter.required, @@ -14852,12 +15010,12 @@ var lib_plankton; "type": "string", }, "description": (header_parameter.description ?? undefined), - })), - // path parameters - lib_plankton.call.convey(steps_, [ - x => x.map(y => wildcard_step_decode(y)), - x => x.filter(y => (!(y === null))), - x => x.map(y => ({ + }))) + // path parameters + .concat(lib_plankton.call.convey(steps_, [ + (x) => x.map(y => wildcard_step_decode(y)), + (x) => x.filter(y => (!(y === null))), + (x) => x.map(y => ({ "name": y, "in": "path", "required": true, @@ -14865,9 +15023,10 @@ var lib_plankton; "type": "string", }, })), - ]), - // query parameters - operation.query_parameters(option_version).map((query_parameter) => ({ + ])) + // query parameters + .concat(operation.query_parameters(option_version) + .map((query_parameter) => ({ "name": query_parameter.name, "in": "query", "required": query_parameter.required, @@ -14875,7 +15034,7 @@ var lib_plankton; "type": "string", }, "description": (query_parameter.description ?? undefined), - }))), + })))), "requestBody": ((!has_body(http_method)) ? undefined : { @@ -14907,8 +15066,8 @@ var lib_plankton; ]), ]; }), - x => x.filter(y => (Object.keys(y[1]).length > 0)), - x => Object.fromEntries(x), + (x) => x.filter(y => (Object.keys(y[1]).length > 0)), + (x) => Object.fromEntries(x), ]) }; }