nsj-rest-lib2 0.0.35__py3-none-any.whl → 0.0.37__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28,6 +28,7 @@ from nsj_rest_lib2.compiler.util.type_naming_util import (
28
28
  compile_entity_class_name,
29
29
  compile_namespace_keys,
30
30
  )
31
+ from nsj_rest_lib2.compiler.response_dto_compiler import ResponseDTOCompiler
31
32
  from nsj_rest_lib2.compiler.util.relation_ref import RelationRefParser
32
33
 
33
34
  from nsj_rest_lib2.compiler.edl_model.entity_model import EntityModel
@@ -169,9 +170,12 @@ class EDLCompiler:
169
170
  get_function_name = None
170
171
  list_function_name = None
171
172
  delete_function_name = None
173
+ handlers: dict[str, Any] = {}
174
+ post_handler = None
175
+ put_handler = None
176
+ patch_handler = None
172
177
 
173
178
  if isinstance(entity_model, EntityModel) and entity_model.api:
174
- handlers = {}
175
179
  if entity_model.api.handlers:
176
180
  handlers = {
177
181
  (verb or "").lower(): handler
@@ -179,16 +183,20 @@ class EDLCompiler:
179
183
  if handler
180
184
  }
181
185
 
186
+ post_handler = handlers.get("post")
187
+ put_handler = handlers.get("put")
188
+ patch_handler = handlers.get("patch")
189
+
182
190
  insert_output = self._function_compiler.compile_insert(
183
191
  entity_model,
184
192
  properties_structure,
185
- handlers.get("post"),
193
+ post_handler,
186
194
  prefx_class_name,
187
195
  )
188
196
  update_output = self._function_compiler.compile_update(
189
197
  entity_model,
190
198
  properties_structure,
191
- handlers.get("put"),
199
+ put_handler,
192
200
  prefx_class_name,
193
201
  )
194
202
  get_handler = handlers.get("get")
@@ -354,6 +362,16 @@ class EDLCompiler:
354
362
  # Adicionando as dependências das relações
355
363
  relations_dependencies_complete.extend(relations_dependencies)
356
364
 
365
+ response_dto_compiler = ResponseDTOCompiler(
366
+ dto_compiler=self._dto_compiler,
367
+ entity_model=entity_model,
368
+ prefx_class_name=prefx_class_name,
369
+ ast_dto_attributes=ast_dto_attributes,
370
+ aux_classes=aux_classes,
371
+ related_imports=related_imports,
372
+ fixed_filters=fixed_filters,
373
+ )
374
+
357
375
  # Adicionando as dependências da extensão parcial
358
376
  if partial_metadata and partial_base_model:
359
377
  relation_dependency = RelationDependency()
@@ -367,6 +385,68 @@ class EDLCompiler:
367
385
  relation_dependency.grupo_empresarial = partial_base_model.grupo_empresarial
368
386
  relations_dependencies_complete.append(relation_dependency)
369
387
 
388
+ post_expected = "empty"
389
+ put_expected = "empty"
390
+ patch_expected = "empty"
391
+ get_expected = "empty"
392
+ list_expected = "empty"
393
+ delete_expected = "empty"
394
+ post_properties = None
395
+ put_properties = None
396
+ patch_properties = None
397
+ if isinstance(entity_model, EntityModel) and entity_model.api:
398
+ post_expected, post_properties = (
399
+ response_dto_compiler.handler_result_details(post_handler)
400
+ )
401
+ put_expected, put_properties = (
402
+ response_dto_compiler.handler_result_details(put_handler)
403
+ )
404
+ patch_expected, patch_properties = (
405
+ response_dto_compiler.handler_result_details(patch_handler)
406
+ )
407
+ get_expected, _ = response_dto_compiler.handler_result_details(
408
+ get_handler
409
+ )
410
+ list_expected, _ = response_dto_compiler.handler_result_details(
411
+ list_handler
412
+ )
413
+ delete_expected, _ = response_dto_compiler.handler_result_details(
414
+ delete_handler
415
+ )
416
+
417
+ if post_expected == "partial_row":
418
+ post_class_name, post_code = (
419
+ response_dto_compiler.compile_partial_response_dto(
420
+ "post", post_properties or []
421
+ )
422
+ )
423
+ compiler_result_post_class = post_class_name
424
+ dto_code += "\n\n" + post_code
425
+ else:
426
+ compiler_result_post_class = None
427
+
428
+ if put_expected == "partial_row":
429
+ put_class_name, put_code = (
430
+ response_dto_compiler.compile_partial_response_dto(
431
+ "put", put_properties or []
432
+ )
433
+ )
434
+ compiler_result_put_class = put_class_name
435
+ dto_code += "\n\n" + put_code
436
+ else:
437
+ compiler_result_put_class = None
438
+
439
+ if patch_expected == "partial_row":
440
+ patch_class_name, patch_code = (
441
+ response_dto_compiler.compile_partial_response_dto(
442
+ "patch", patch_properties or []
443
+ )
444
+ )
445
+ compiler_result_patch_class = patch_class_name
446
+ dto_code += "\n\n" + patch_code
447
+ else:
448
+ compiler_result_patch_class = None
449
+
370
450
  # Construindo o resultado
371
451
  compiler_result = CompilerResult()
372
452
  compiler_result.entity_class_name = entity_class_name
@@ -389,6 +469,34 @@ class EDLCompiler:
389
469
  compiler_result.source_delete_function_type = (
390
470
  delete_function_code.strip() or None
391
471
  )
472
+ compiler_result.retrieve_after_insert = post_expected == "entity_row"
473
+ compiler_result.retrieve_after_update = put_expected == "entity_row"
474
+ compiler_result.retrieve_after_partial_update = (
475
+ patch_expected == "entity_row"
476
+ )
477
+ compiler_result.post_response_dto_class_name = compiler_result_post_class
478
+ compiler_result.put_response_dto_class_name = compiler_result_put_class
479
+ compiler_result.patch_response_dto_class_name = (
480
+ compiler_result_patch_class
481
+ )
482
+ compiler_result.custom_json_post_response = (
483
+ post_expected == "custom_json"
484
+ )
485
+ compiler_result.custom_json_put_response = (
486
+ put_expected == "custom_json"
487
+ )
488
+ compiler_result.custom_json_patch_response = (
489
+ patch_expected == "custom_json"
490
+ )
491
+ compiler_result.custom_json_get_response = (
492
+ get_expected == "custom_json"
493
+ )
494
+ compiler_result.custom_json_list_response = (
495
+ list_expected == "custom_json"
496
+ )
497
+ compiler_result.custom_json_delete_response = (
498
+ delete_expected == "custom_json"
499
+ )
392
500
 
393
501
  insert_code_compiled = insert_function_code.strip()
394
502
  update_code_compiled = update_function_code.strip()
@@ -1,4 +1,5 @@
1
1
  import ast
2
+ from typing import Optional
2
3
 
3
4
  import black
4
5
 
@@ -21,6 +22,7 @@ class DTOCompiler:
21
22
  fixed_filters: list[tuple[str, BasicTypes]],
22
23
  prefx_class_name: str,
23
24
  partial_metadata: dict[str, str] | None,
25
+ class_name_override: Optional[str] = None,
24
26
  ) -> tuple[str, str]:
25
27
  """
26
28
  Compila o código do DTO a partir do AST e retorna o código compilado.
@@ -158,7 +160,9 @@ class DTOCompiler:
158
160
  )
159
161
 
160
162
  # Criando o ast da classe
161
- class_name = compile_dto_class_name(entity_model.id, prefx_class_name)
163
+ class_name = class_name_override or compile_dto_class_name(
164
+ entity_model.id, prefx_class_name
165
+ )
162
166
  ast_class = ast.ClassDef(
163
167
  name=class_name,
164
168
  bases=[ast.Name(id="DTOBase", ctx=ast.Load())],
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from typing import Dict, List, Literal, Optional
4
4
 
5
- from pydantic import AliasChoices, BaseModel, Field
5
+ from pydantic import AliasChoices, BaseModel, Field, model_validator
6
6
 
7
7
  APIVerbs = Literal["GET", "POST", "PUT", "DELETE", "PATCH"]
8
8
 
@@ -46,10 +46,22 @@ class HandlerCall(BaseModel):
46
46
 
47
47
 
48
48
  class HandlerResult(BaseModel):
49
- expected: Literal["empty", "entity_row"] = Field(
49
+ expected: Literal["empty", "entity_row", "custom_json", "partial_row"] = Field(
50
50
  default="empty",
51
51
  description="Define o formato esperado do retorno da função.",
52
52
  )
53
+ properties: Optional[List[str]] = Field(
54
+ default=None,
55
+ description="Lista de propriedades a serem retornadas quando o resultado esperado for 'partial_row'.",
56
+ )
57
+
58
+ @model_validator(mode="after")
59
+ def validate_partial_row(self):
60
+ if self.expected == "partial_row" and not self.properties:
61
+ raise ValueError(
62
+ "result.properties é obrigatório quando result.expected for 'partial_row'."
63
+ )
64
+ return self
53
65
 
54
66
 
55
67
  class HandlerError(BaseModel):
@@ -68,12 +80,12 @@ class HandlerError(BaseModel):
68
80
 
69
81
 
70
82
  class HandlerConfig(BaseModel):
71
- impl: Literal["pg_function"] = Field(
72
- ...,
83
+ impl: Optional[Literal["pg_function"]] = Field(
84
+ default=None,
73
85
  description="Somente funções PostgreSQL (pg_function) são suportadas neste estágio.",
74
86
  )
75
- function_ref: str = Field(
76
- ...,
87
+ function_ref: Optional[str] = Field(
88
+ default=None,
77
89
  description="Referência qualificada para a função no banco (ex.: schema.fn_nome).",
78
90
  )
79
91
  call: Optional[HandlerCall] = Field(
@@ -59,3 +59,15 @@ class CompilerResult:
59
59
  self.source_get_function_type: str | None = None
60
60
  self.source_list_function_type: str | None = None
61
61
  self.source_delete_function_type: str | None = None
62
+ self.retrieve_after_insert: bool | None = None
63
+ self.retrieve_after_update: bool | None = None
64
+ self.retrieve_after_partial_update: bool | None = None
65
+ self.post_response_dto_class_name: str | None = None
66
+ self.put_response_dto_class_name: str | None = None
67
+ self.patch_response_dto_class_name: str | None = None
68
+ self.custom_json_post_response: bool | None = None
69
+ self.custom_json_put_response: bool | None = None
70
+ self.custom_json_patch_response: bool | None = None
71
+ self.custom_json_get_response: bool | None = None
72
+ self.custom_json_list_response: bool | None = None
73
+ self.custom_json_delete_response: bool | None = None
@@ -0,0 +1,104 @@
1
+ from __future__ import annotations
2
+
3
+ import ast
4
+ from typing import Any, Optional
5
+
6
+ from nsj_rest_lib2.compiler.dto_compiler import DTOCompiler
7
+ from nsj_rest_lib2.compiler.edl_model.entity_model_base import EntityModelBase
8
+ from nsj_rest_lib2.compiler.edl_model.primitives import BasicTypes
9
+ from nsj_rest_lib2.compiler.util.str_util import CompilerStrUtil
10
+ from nsj_rest_lib2.compiler.util.type_naming_util import (
11
+ compile_response_dto_class_name,
12
+ )
13
+
14
+
15
+ class ResponseDTOCompiler:
16
+ def __init__(
17
+ self,
18
+ dto_compiler: DTOCompiler,
19
+ entity_model: EntityModelBase,
20
+ prefx_class_name: str,
21
+ ast_dto_attributes: list[ast.stmt],
22
+ aux_classes: list[ast.stmt],
23
+ related_imports: list[tuple[str, str, str]],
24
+ fixed_filters: list[tuple[str, BasicTypes]],
25
+ ) -> None:
26
+ self._dto_compiler = dto_compiler
27
+ self._entity_model = entity_model
28
+ self._prefx_class_name = prefx_class_name
29
+ self._aux_classes = aux_classes
30
+ self._related_imports = related_imports
31
+ self._fixed_filters = fixed_filters
32
+ self._dto_attr_map = self._build_attr_map(ast_dto_attributes)
33
+
34
+ @staticmethod
35
+ def handler_result_details(handler: Any) -> tuple[str, list[str] | None]:
36
+ expected = "empty"
37
+ properties = None
38
+ if handler and getattr(handler, "result", None):
39
+ expected = handler.result.expected or "empty"
40
+ properties = handler.result.properties
41
+ return (expected, properties)
42
+
43
+ def compile_partial_response_dto(
44
+ self, verb: str, properties: list[str]
45
+ ) -> tuple[str, str]:
46
+ if not properties:
47
+ raise Exception(
48
+ f"result.properties não pode ser vazio para '{verb}' na entidade '{self._entity_model.id}'."
49
+ )
50
+
51
+ normalized = [
52
+ CompilerStrUtil.to_snake_case(prop) for prop in properties
53
+ ]
54
+ missing = [
55
+ properties[idx]
56
+ for idx, norm in enumerate(normalized)
57
+ if norm not in self._dto_attr_map
58
+ ]
59
+ if missing:
60
+ raise Exception(
61
+ f"As propriedades {missing} não foram encontradas na entidade '{self._entity_model.id}'."
62
+ )
63
+
64
+ filtered_attrs = [self._dto_attr_map[name] for name in normalized]
65
+ filtered_fixed_filters = [
66
+ item for item in self._fixed_filters if item[0] in normalized
67
+ ]
68
+
69
+ class_name = compile_response_dto_class_name(
70
+ self._entity_model.id,
71
+ self._prefx_class_name,
72
+ verb,
73
+ )
74
+
75
+ return self._dto_compiler.compile(
76
+ self._entity_model,
77
+ filtered_attrs,
78
+ self._aux_classes,
79
+ self._related_imports,
80
+ filtered_fixed_filters,
81
+ self._prefx_class_name,
82
+ None,
83
+ class_name_override=class_name,
84
+ )
85
+
86
+ @staticmethod
87
+ def _extract_attr_name(stmt: ast.stmt) -> Optional[str]:
88
+ if isinstance(stmt, ast.AnnAssign) and isinstance(stmt.target, ast.Name):
89
+ return stmt.target.id
90
+ if isinstance(stmt, ast.Assign) and stmt.targets:
91
+ target = stmt.targets[0]
92
+ if isinstance(target, ast.Name):
93
+ return target.id
94
+ return None
95
+
96
+ def _build_attr_map(
97
+ self, ast_dto_attributes: list[ast.stmt]
98
+ ) -> dict[str, ast.stmt]:
99
+ dto_attr_map: dict[str, ast.stmt] = {}
100
+ for stmt in ast_dto_attributes:
101
+ name = self._extract_attr_name(stmt)
102
+ if name:
103
+ dto_attr_map[name] = stmt
104
+ return dto_attr_map
@@ -1,6 +1,8 @@
1
+ import hashlib
1
2
  import uuid
2
- from typing import Iterable
3
+ from typing import Iterable, Iterator, Optional
3
4
 
5
+ from nsj_rest_lib2.compiler.model import CompilerResult
4
6
  from nsj_rest_lib2.compiler.util.str_util import CompilerStrUtil
5
7
 
6
8
 
@@ -14,10 +16,90 @@ def compile_namespace_keys(
14
16
  return (grupo_key, tenant_key, default_key)
15
17
 
16
18
 
19
+ def resolve_namespace_key(
20
+ tenant: str | int | None, grupo_empresarial: str | uuid.UUID | None
21
+ ) -> str:
22
+ grupo_key, tenant_key, default_key = compile_namespace_keys(
23
+ tenant,
24
+ grupo_empresarial,
25
+ )
26
+
27
+ if (
28
+ tenant
29
+ and tenant != 0
30
+ and grupo_empresarial
31
+ and str(grupo_empresarial) != "00000000-0000-0000-0000-000000000000"
32
+ ):
33
+ return grupo_key
34
+ if tenant and tenant != 0:
35
+ return tenant_key
36
+ return default_key
37
+
38
+
39
+ def build_entity_hash(compiler_result: CompilerResult) -> str:
40
+ hasher = hashlib.sha256()
41
+
42
+ for content in _iter_hash_chunks(
43
+ compiler_result.dto_code,
44
+ compiler_result.entity_code,
45
+ compiler_result.insert_function_name,
46
+ compiler_result.update_function_name,
47
+ compiler_result.get_function_name,
48
+ compiler_result.list_function_name,
49
+ compiler_result.delete_function_name,
50
+ compiler_result.source_insert_function,
51
+ compiler_result.source_update_function,
52
+ compiler_result.source_get_function_type,
53
+ compiler_result.source_list_function_type,
54
+ compiler_result.source_delete_function_type,
55
+ compiler_result.post_response_dto_class_name,
56
+ compiler_result.put_response_dto_class_name,
57
+ compiler_result.patch_response_dto_class_name,
58
+ str(compiler_result.retrieve_after_insert),
59
+ str(compiler_result.retrieve_after_update),
60
+ str(compiler_result.retrieve_after_partial_update),
61
+ str(compiler_result.custom_json_post_response),
62
+ str(compiler_result.custom_json_put_response),
63
+ str(compiler_result.custom_json_patch_response),
64
+ str(compiler_result.custom_json_get_response),
65
+ str(compiler_result.custom_json_list_response),
66
+ str(compiler_result.custom_json_delete_response),
67
+ compiler_result.service_account,
68
+ ):
69
+ hasher.update(content)
70
+
71
+ return hasher.hexdigest()
72
+
73
+
74
+ def _iter_hash_chunks(*chunks: Optional[str]) -> Iterator[bytes]:
75
+ for chunk in chunks:
76
+ if chunk:
77
+ yield chunk.encode("utf-8")
78
+
79
+
17
80
  def compile_dto_class_name(entity_id: str, prefx_class_name: str = "") -> str:
18
81
  return f"{CompilerStrUtil.to_pascal_case(prefx_class_name)}{CompilerStrUtil.to_pascal_case(entity_id)}DTO"
19
82
 
20
83
 
84
+ def compile_response_dto_class_name(
85
+ entity_id: str, prefx_class_name: str, verb: str
86
+ ) -> str:
87
+ verb = (verb or "").lower()
88
+ suffix_map = {
89
+ "post": "PostResponseDTO",
90
+ "put": "PutResponseDTO",
91
+ "patch": "PatchResponseDTO",
92
+ }
93
+ suffix = suffix_map.get(
94
+ verb, f"{CompilerStrUtil.to_pascal_case(verb)}ResponseDTO"
95
+ )
96
+ return (
97
+ f"{CompilerStrUtil.to_pascal_case(prefx_class_name)}"
98
+ f"{CompilerStrUtil.to_pascal_case(entity_id)}"
99
+ f"{suffix}"
100
+ )
101
+
102
+
21
103
  def compile_entity_class_name(entity_id: str, prefx_class_name: str = "") -> str:
22
104
  return f"{CompilerStrUtil.to_pascal_case(prefx_class_name)}{CompilerStrUtil.to_pascal_case(entity_id)}Entity"
23
105
 
@@ -11,12 +11,12 @@ from nsj_gcf_utils.rest_error_util import format_json_error
11
11
  from nsj_multi_database_lib.decorator.multi_database import multi_database
12
12
 
13
13
  from nsj_rest_lib.controller.controller_util import DEFAULT_RESP_HEADERS
14
- from nsj_rest_lib.controller.list_route import ListRoute
14
+ from nsj_rest_lib.controller.delete_route import DeleteRoute
15
15
  from nsj_rest_lib.controller.get_route import GetRoute
16
+ from nsj_rest_lib.controller.list_route import ListRoute
17
+ from nsj_rest_lib.controller.patch_route import PatchRoute
16
18
  from nsj_rest_lib.controller.post_route import PostRoute
17
19
  from nsj_rest_lib.controller.put_route import PutRoute
18
- from nsj_rest_lib.controller.patch_route import PatchRoute
19
- from nsj_rest_lib.controller.delete_route import DeleteRoute
20
20
 
21
21
  from nsj_rest_lib2.exception import MissingEntityConfigException
22
22
  from nsj_rest_lib2.service.entity_loader import EntityLoader
@@ -55,6 +55,7 @@ def setup_dynamic_routes(
55
55
  dynamic_root_path: str = "edl1",
56
56
  injector_factory: Any = None,
57
57
  escopo_in_url: bool = False,
58
+ edls_path: str | None = None,
58
59
  ) -> None:
59
60
 
60
61
  if not escopo_in_url:
@@ -68,6 +69,8 @@ def setup_dynamic_routes(
68
69
  f"/{APP_NAME}/{dynamic_root_path}/<entity_escopo>/<entity_resource>/<id>"
69
70
  )
70
71
 
72
+ entity_loader = EntityLoader(edls_path=edls_path)
73
+
71
74
  def _dynamic_route_wrapper(
72
75
  route_builder: Callable[[tuple[Any, ...]], Callable[..., Any]],
73
76
  endpoint_suffix: str | None = None,
@@ -83,7 +86,6 @@ def setup_dynamic_routes(
83
86
  tenant, grupo_empresarial, force_reload = _get_query_args()
84
87
 
85
88
  try:
86
- entity_loader = EntityLoader()
87
89
  entity_config = entity_loader.load_entity_source(
88
90
  entity_resource,
89
91
  tenant,
@@ -133,6 +135,10 @@ def setup_dynamic_routes(
133
135
  _get_function_type_class_name,
134
136
  list_function_type_class_name,
135
137
  _delete_function_type_class_name,
138
+ *_,
139
+ _custom_json_get_response,
140
+ custom_json_list_response,
141
+ _custom_json_delete_response,
136
142
  ) = entity_config
137
143
 
138
144
  def list_dynamic(*args: Any, **kwargs: Any) -> Any:
@@ -149,6 +155,7 @@ def setup_dynamic_routes(
149
155
  list_function_type_class=etities_dict.get(
150
156
  list_function_type_class_name
151
157
  ),
158
+ custom_json_response=bool(custom_json_list_response),
152
159
  )
153
160
 
154
161
  return route.handle_request(*args, **kwargs)
@@ -173,6 +180,10 @@ def setup_dynamic_routes(
173
180
  get_function_type_class_name,
174
181
  _list_function_type_class_name,
175
182
  _delete_function_type_class_name,
183
+ *_,
184
+ custom_json_get_response,
185
+ _custom_json_list_response,
186
+ _custom_json_delete_response,
176
187
  ) = entity_config
177
188
 
178
189
  def get_dynamic(*args: Any, **kwargs: Any) -> Any:
@@ -187,6 +198,7 @@ def setup_dynamic_routes(
187
198
  injector_factory=injector_factory,
188
199
  get_function_name=get_function_name,
189
200
  get_function_type_class=etities_dict.get(get_function_type_class_name),
201
+ custom_json_response=bool(custom_json_get_response),
190
202
  )
191
203
 
192
204
  return route.handle_request(*args, **kwargs)
@@ -211,6 +223,18 @@ def setup_dynamic_routes(
211
223
  _get_function_type_class_name,
212
224
  _list_function_type_class_name,
213
225
  _delete_function_type_class_name,
226
+ retrieve_after_insert,
227
+ _retrieve_after_update,
228
+ _retrieve_after_partial_update,
229
+ post_response_dto_class_name,
230
+ _put_response_dto_class_name,
231
+ _patch_response_dto_class_name,
232
+ custom_json_post_response,
233
+ _custom_json_put_response,
234
+ _custom_json_patch_response,
235
+ _custom_json_get_response,
236
+ _custom_json_list_response,
237
+ _custom_json_delete_response,
214
238
  ) = entity_config
215
239
 
216
240
  def post_dynamic(*args: Any, **kwargs: Any) -> Any:
@@ -223,6 +247,12 @@ def setup_dynamic_routes(
223
247
  else None
224
248
  )
225
249
 
250
+ dto_response_class = (
251
+ etities_dict.get(post_response_dto_class_name)
252
+ if post_response_dto_class_name
253
+ else None
254
+ )
255
+
226
256
  route = PostRoute(
227
257
  url=COLLECTION_DYNAMIC_ROUTE,
228
258
  http_method="POST",
@@ -231,6 +261,9 @@ def setup_dynamic_routes(
231
261
  injector_factory=injector_factory,
232
262
  insert_function_type_class=insert_function_type_class,
233
263
  insert_function_name=insert_function_name,
264
+ dto_response_class=dto_response_class,
265
+ retrieve_after_insert=retrieve_after_insert,
266
+ custom_json_response=bool(custom_json_post_response),
234
267
  )
235
268
 
236
269
  return route.handle_request(*args, **kwargs)
@@ -255,8 +288,26 @@ def setup_dynamic_routes(
255
288
  _get_function_type_class_name,
256
289
  _list_function_type_class_name,
257
290
  _delete_function_type_class_name,
291
+ _retrieve_after_insert,
292
+ retrieve_after_update,
293
+ _retrieve_after_partial_update,
294
+ _post_response_dto_class_name,
295
+ put_response_dto_class_name,
296
+ _patch_response_dto_class_name,
297
+ _custom_json_post_response,
298
+ custom_json_put_response,
299
+ _custom_json_patch_response,
300
+ _custom_json_get_response,
301
+ _custom_json_list_response,
302
+ _custom_json_delete_response,
258
303
  ) = entity_config
259
304
 
305
+ dto_response_class = (
306
+ etities_dict.get(put_response_dto_class_name)
307
+ if put_response_dto_class_name
308
+ else None
309
+ )
310
+
260
311
  def put_dynamic(*args: Any, **kwargs: Any) -> Any:
261
312
  if not api_expose or "PUT" not in api_verbs:
262
313
  return ("", 405, {})
@@ -275,6 +326,9 @@ def setup_dynamic_routes(
275
326
  injector_factory=injector_factory,
276
327
  update_function_type_class=update_function_type_class,
277
328
  update_function_name=update_function_name,
329
+ dto_response_class=dto_response_class,
330
+ retrieve_after_update=retrieve_after_update,
331
+ custom_json_response=bool(custom_json_put_response),
278
332
  )
279
333
 
280
334
  return route.handle_request(*args, **kwargs)
@@ -296,19 +350,42 @@ def setup_dynamic_routes(
296
350
  _get_function_name,
297
351
  _list_function_name,
298
352
  _delete_function_name,
299
- *_,
353
+ _get_function_type_class_name,
354
+ _list_function_type_class_name,
355
+ _delete_function_type_class_name,
356
+ _retrieve_after_insert,
357
+ _retrieve_after_update,
358
+ retrieve_after_partial_update,
359
+ _post_response_dto_class_name,
360
+ _put_response_dto_class_name,
361
+ patch_response_dto_class_name,
362
+ _custom_json_post_response,
363
+ _custom_json_put_response,
364
+ custom_json_patch_response,
365
+ _custom_json_get_response,
366
+ _custom_json_list_response,
367
+ _custom_json_delete_response,
300
368
  ) = entity_config
301
369
 
302
370
  def patch_dynamic(*args: Any, **kwargs: Any) -> Any:
303
371
  if not api_expose or "PATCH" not in api_verbs:
304
372
  return ("", 405, {})
305
373
 
374
+ dto_response_class = (
375
+ etities_dict.get(patch_response_dto_class_name)
376
+ if patch_response_dto_class_name
377
+ else None
378
+ )
379
+
306
380
  route = PatchRoute(
307
381
  url=ONE_DYNAMIC_ROUTE,
308
382
  http_method="PATCH",
309
383
  dto_class=etities_dict[dto_class_name],
310
384
  entity_class=etities_dict[entity_class_name],
311
385
  injector_factory=injector_factory,
386
+ dto_response_class=dto_response_class,
387
+ retrieve_after_partial_update=retrieve_after_partial_update,
388
+ custom_json_response=bool(custom_json_patch_response),
312
389
  )
313
390
 
314
391
  return route.handle_request(*args, **kwargs)
@@ -333,6 +410,10 @@ def setup_dynamic_routes(
333
410
  _get_function_type_class_name,
334
411
  _list_function_type_class_name,
335
412
  delete_function_type_class_name,
413
+ *_,
414
+ _custom_json_get_response,
415
+ _custom_json_list_response,
416
+ custom_json_delete_response,
336
417
  ) = entity_config
337
418
 
338
419
  def delete_dynamic(*args: Any, **kwargs: Any) -> Any:
@@ -349,6 +430,7 @@ def setup_dynamic_routes(
349
430
  delete_function_type_class=etities_dict.get(
350
431
  delete_function_type_class_name
351
432
  ),
433
+ custom_json_response=bool(custom_json_delete_response),
352
434
  )
353
435
 
354
436
  return route.handle_request(*args, **kwargs)