From b53f539a9803edcb523373ffa7b0f2d5255da913 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= <gp5761@partner.kit.edu>
Date: Mon, 10 Mar 2025 17:13:52 +0100
Subject: [PATCH] WIP: Generate Listing API-Calls + Manipulating API-Calls

---
 net_api_generator/generator.py | 221 +++++++++++++++------------------
 1 file changed, 100 insertions(+), 121 deletions(-)

diff --git a/net_api_generator/generator.py b/net_api_generator/generator.py
index 6512d63..c7cfb65 100644
--- a/net_api_generator/generator.py
+++ b/net_api_generator/generator.py
@@ -309,142 +309,121 @@ def typescript(output_dir):
         code_template = code_template.replace("$API_OBJECT_NAME", api_object.name.capitalize())
         return code_template
 
+    def seperate_parameters_by_scope(parameters: dict[str, FunctionParameter]) -> dict[str, list]:
+        seperated_parameters = {
+            "old": [],
+            "new": []
+        }
+        for parameter in parameters.values():
+            if parameter.old is not None:
+                seperated_parameters["old"].append(parameter)
+            if parameter.new is not None:
+                seperated_parameters["new"].append(parameter)
+        return seperated_parameters
+
+
+
     def generate_api_function(api_function: ApiFunction)->str:
-        def generate_api_list_call()->str:
-            api_call = ("$METHOD_NAME (config: AxiosConfig, $FUNCTION_PARAMETER): Promise<UseAxiosReturn<$API_OBJECT_TYPE>> {\n\n"
-                        "\tconst axiosRequestConfig<any> = {\n"
-                        "\t\tmethod: '$HTTP_METHOD',\n"
-                        "\t\tparams: APIUtils.denullify_dict({\n"
-                        "\t\t\t$PARAMETER\n"
-                        "\t\t}),\n"
-                        "\t\tbaseURL: config.baseUrl,\n"
-                        "\t\theaders: config.headers,\n"
-                        "\t}\n\n"
-                        "\tconst url: string `${NETVSConfig.NETDB_API_BASE_URL}/${NETVSConfig.NETDB_API_VERSION}/$PATH`\n"
-                        "\treturn useAxios(url, axiosRequestConfig)\n"
-                        "}")
-
-            # todo: what is api_function.isReturning and api_function.isReturningReferenceable and api_function.isExecuteable telling?
-
-            api_call = api_call.replace("$METHOD_NAME", api_function.name)
-            api_call = api_call.replace("$API_OBJECT_TYPE", api_function.object_type.capitalize())
-            api_call = api_call.replace("$HTTP_METHOD", "POST" if api_function.is_data_manipulating else "GET")
-            api_call = api_call.replace("$PATH", api_function.fq_name.replace(".", "/"))
-
-            method_signature_opening_bracket_index = api_call.index("(")
-            method_signature_closing_bracket_index = api_call.index(")")
-            signature_length = method_signature_closing_bracket_index - method_signature_opening_bracket_index
-            for i, parameter in enumerate(api_function.parameters.values()):
-                data_type: str = map_netdb_type_to_typescript_type(parameter.data_type)
-                function_parameter = parameter.name + ": " + data_type
-                if i < len(api_function.parameters) - 1:
-                    signature_length += len(function_parameter)
-                    if signature_length > 120:
-                        ident = " "* (len (api_function.name) + 2)
-                        function_parameter += ",\n" + ident + "$FUNCTION_PARAMETER"
-                        signature_length = method_signature_closing_bracket_index - method_signature_opening_bracket_index
+        api_call = ("$METHOD_NAME (config: AxiosConfig, $FUNCTION_PARAMETER) $RETURN_TYPE {\n"
+                    "\tconst requestData = $REQUEST_DATA\n\n"
+                    
+                    "\tconst axiosRequestConfig: AxiosRequestConfig<$AXIOS_REQUEST_DATA> = {\n"
+                    "\t\tmethod: $HTTP_METHOD,\n"
+                    "\t\tbaseUrl: config.baseUrl, \n"
+                    "\t\theaders: config.headers\n"
+                    "\t\t$PARAMS_OR_REQUEST_BODY: requestData\n" 
+                    "\t}\n\n"
+                    "\tconst url = `${NETVSConfig.NETDB_API_BASE_URL}/${NETVSConfig.NETDB_API_VERSION}/$PATH`\n"
+                    "\t$RETURN_ENABLED useAxios(url, axiosRequestConfig)\n"
+                    "}")
+
+        api_call = api_call.replace("$PARAMS_OR_REQUEST_BODY", "data" if api_function.is_data_manipulating else "params")
+        api_call = api_call.replace("$METHOD_NAME", api_function.name)
+        api_call = api_call.replace("$HTTP_METHOD", "POST" if api_function.is_data_manipulating else "GET")
+        api_call = api_call.replace("$PATH", api_function.fq_name.replace(".", "/"))
+
+        return_type = f"Promise<UseAxiosReturn<{api_function.object_type.capitalize()}>>" if api_function.is_returning else ""
+        api_call = api_call.replace("$RETURN_TYPE", return_type)
+        api_call = api_call.replace("$RETURN_ENABLED", "return" if api_function.is_returning else "")
+
+        # generate function signature (function parameters especially
+        seperated_parameters = seperate_parameters_by_scope(api_function.parameters)
+        parameter_counter = 0
+        indent = api_call.index("(")
+        signature_length = indent
+        function_parameters = ""
+        request_data = {"old": "", "new": ""}
+        for parameter_scope, parameter_list in seperated_parameters.items():
+            for i, parameter in enumerate(parameter_list):
+                parameter_definition = "'$PARAMETER_NAME': $PARAMETER_NAME_REFERENCE" if i > 0 else "\t\t'$PARAMETER_NAME': $PARAMETER_NAME_REFERENCE"
+                if api_function.is_data_manipulating:
+                    function_parameter_item = f"{parameter.name}_{parameter_scope}: {map_netdb_type_to_typescript_type(parameter.data_type)}"
+                    request_data[parameter_scope] += f"f{parameter.name}: {parameter.name}_{parameter_scope}"
+                    if i < len(parameter_list) - 1:
+                        request_data[parameter_scope] += ", \n\t\t\t"
+                else:
+                    function_parameter_item = f"{parameter.name}: {map_netdb_type_to_typescript_type(parameter.data_type)}"
+                    if parameter.data_type['json_name'] == "array":
+                        parameter_definition = parameter_definition.replace("$PARAMETER_NAME_REFERENCE",
+                                                                            "($PARAMETER_NAME === null) ? null: JSON.stringify($PARAMETER_NAME)")
                     else:
-                        function_parameter += ", $FUNCTION_PARAMETER"
+                        parameter_definition = parameter_definition.replace("$PARAMETER_NAME_REFERENCE",
+                                                                            "$PARAMETER_NAME")
 
-                api_call = api_call.replace("$FUNCTION_PARAMETER", function_parameter)
+                    parameter_definition = parameter_definition.replace("$PARAMETER_NAME", parameter.name)
+                    if parameter_counter < len(api_function.parameters) - 1:
+                        parameter_definition += ",\n\t\t"
+                    request_data["old"] += parameter_definition
 
-                parameter_definition = "'$PARAMETER_NAME': $PARAMETER_NAME_REFERENCE"
-                if parameter.data_type['json_name'] == "array":
-                    parameter_definition = parameter_definition.replace("$PARAMETER_NAME_REFERENCE", "($PARAMETER_NAME === null) ? null: JSON.stringify($PARAMETER_NAME)")
+                if parameter_counter < len(api_function.parameters.values()) - 1:
+                    if signature_length > 120:
+                        function_parameters += function_parameter_item + "\n" + " " * (indent + 1)
+                        signature_length = indent
+                    else:
+                        function_parameters += function_parameter_item + ", "
+                        signature_length += len(function_parameter_item)
                 else:
-                    parameter_definition = parameter_definition.replace("$PARAMETER_NAME_REFERENCE", "$PARAMETER_NAME")
-
-                parameter_definition = parameter_definition.replace("$PARAMETER_NAME", parameter.name)
+                    function_parameters += function_parameter_item
 
-                if i < len(api_function.parameters) - 1:
-                    parameter_definition += ",\n\t\t\t$PARAMETER"
-                api_call = api_call.replace("$PARAMETER", parameter_definition)
+                parameter_counter += 1
 
-            return api_call
 
+        api_call = api_call.replace("$FUNCTION_PARAMETER", function_parameters)
 
-        def generate_api_data_manipulating_call()->str:
-            def seperate_parameters_by_scope(parameters: dict[str, FunctionParameter])->dict[str, list]:
-                seperated_parameters = {
-                    "old": [],
-                    "new": []
-                }
-                for parameter in parameters.values():
-                    if parameter.old is not None:
-                        seperated_parameters["old"].append(parameter)
-                    if parameter.new is not None:
-                        seperated_parameters["new"].append(parameter)
-                return seperated_parameters
-
-            def generate_update_parameters(seperated_parameters: dict[str, list[FunctionParameter]], number_parameters: int, function_parameter_start_index)->tuple[str, str]:
-                function_parameters = ""
-                counter = 0
-                signature_len = function_parameter_start_index
-                for old_parameter in seperated_parameters["old"]:
-                    function_parameter = old_parameter.name + "_old: " + map_netdb_type_to_typescript_type(old_parameter.data_type)
-                    signature_len += len(function_parameter)
-                    if counter < number_parameters - 1:
-                        if signature_len > 120:
-                            function_parameters += function_parameter + ",\n\t\t" + " "*function_parameter_start_index
-                            signature_len = function_parameter_start_index
-                        else:
-                            function_parameters += function_parameter + ", "
-                    else:
-                        function_parameters += function_parameter
-                    counter += 1
-
-                for new_parameter in seperated_parameters["new"]:
-                    function_parameter = new_parameter.name + "_new: " + map_netdb_type_to_typescript_type(new_parameter.data_type)
-                    if counter < number_parameters - 1:
-                        signature_len += len(function_parameter)
-                        if counter < number_parameters - 1:
-                            if signature_len > 120:
-                                function_parameters += function_parameter + ",\n\t\t" + " " * function_parameter_start_index
-                                signature_len = function_parameter_start_index
-                            else:
-                                function_parameters += function_parameter + ", "
-                    else:
-                        function_parameters += function_parameter
-                    counter += 1
-                return function_parameters, ""
-
-            api_call = ("$METHOD_NAME (config: AxiosConfig, $FUNCTION_PARAMETER) $RETURN_TYPE {\n"
-                        "\tconst requestData: $REQUEST_TYPE = {\n"
-                        "\t\t$REQUEST_DATA\n"
-                        "\t}\n\n"
-                        "\tconst axiosRequestConfig<REQUEST_TYPE> = {\n"
-                        "\t\tmethod: '$HTTP_METHOD',\n"
-                        "\t\tdata: requestData, \n"
-                        "\t\tbaseURL: config.baseUrl,\n"
-                        "\t\theaders: config.headers,\n"
-                        "\t}\n\n"
-                        "\tconst url = `${NETVSConfig.NETDB_API_BASE_URL}/${NETVSConfig.NETDB_API_VERSION}/$PATH`\n"
-                        "\treturn useAxios(url, axiosRequestConfig)\n"
-                        "}")
-
-            seperated_parameters = seperate_parameters_by_scope(api_function.parameters)
-            # determine Request_Type (update = old + new; create = new; delete = old)
-            request_type = ""
+        # determine the type of request: Update, Create, Delete or List?
+        request_data_declaration_code = ""
+        if api_function.is_data_manipulating:
             if len(seperated_parameters["old"]) > 0 and len(seperated_parameters["new"]) > 0:
                 request_type = "AxiosUpdateRequestBody<any, any>"
+                request_data_declaration_code = ("{\n"
+                                                 "\t\told: {\n"
+                                                 f"\t\t\t{request_data["old"]},\n"
+                                                 "\t\t}\n"
+                                                 "\t\tnew: {\n"
+                                                 f"\t\t\t{request_data["new"]},\n"
+                                                 "\t\t}")
             elif len(seperated_parameters["old"]) > 0 and len(seperated_parameters["new"]) == 0:
                 request_type = "AxiosDeleteRequestBody<any>"
+                request_data_declaration_code = ("{\n"
+                                                 "\t\told: {\n"
+                                                 f"\t\t\t{request_data["old"]},\n"
+                                                 "\t\t}")
             else:
                 request_type = "AxiosCreateRequestBody<any>"
-
-            api_call = api_call.replace("$REQUEST_TYPE", request_type)
-            api_call = api_call.replace("$FUNCTION_PARAMETER", generate_update_parameters(seperated_parameters, len(api_function.parameters.items()), len(api_function.name))[0])
-
-            if(len(api_function.parameters) > 5):
-                print(api_call)
-
-
-
-
-        if api_function.is_data_manipulating:
-            return generate_api_data_manipulating_call()
+                request_data_declaration_code = ("{\n"
+                                                 "\t\tnew: {\n"
+                                                 f"\t\t\t{request_data["new"]},\n"
+                                                 "\t\t}\n"
+                                                 "\t}")
         else:
-            return generate_api_list_call()
+            request_type = "any"
+            request_data_declaration_code = ("APIUtils.denullify_dict({\n"
+                                             f"{request_data["old"]}\n"
+                                             "\t}")
+        api_call = api_call.replace("$AXIOS_REQUEST_DATA", request_type)
+        api_call = api_call.replace("$REQUEST_DATA", request_data_declaration_code)
+
+        return api_call
 
     def generate_api_object_type_definitions(api_object_items: dict)->dict:
         generated_type_definitions = {}
@@ -464,7 +443,7 @@ def typescript(output_dir):
 
             # todo: temp stuff, remove once finished
             if api_function.is_data_manipulating:
-                pass
+                break
         return generated_api_calls
 
     def unite_generated_code(type_definitions: dict, api_calls: dict) -> dict:
-- 
GitLab