storm-cli 1.0.0__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.
- main.py +753 -0
- src/__init__.py +2 -0
- src/ast.py +100 -0
- src/column.py +56 -0
- src/enum.py +21 -0
- src/error_handler.py +35 -0
- src/generic_controller_csharp.py +106 -0
- src/generic_mapper_csharp.py +35 -0
- src/generic_pagination_csharp.py +44 -0
- src/generic_query_chsarp.py +18 -0
- src/generic_service_csharp.py +112 -0
- src/interpreter.py +2300 -0
- src/keyword.py +18 -0
- src/parser.py +397 -0
- src/pos.py +11 -0
- src/table.py +37 -0
- src/template.py +14 -0
- src/tok.py +12 -0
- src/tok_type.py +13 -0
- src/tokenizer.py +238 -0
- storm_cli-1.0.0.dist-info/METADATA +350 -0
- storm_cli-1.0.0.dist-info/RECORD +26 -0
- storm_cli-1.0.0.dist-info/WHEEL +5 -0
- storm_cli-1.0.0.dist-info/entry_points.txt +2 -0
- storm_cli-1.0.0.dist-info/licenses/LICENSE +21 -0
- storm_cli-1.0.0.dist-info/top_level.txt +2 -0
src/__init__.py
ADDED
src/ast.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import enum
|
|
2
|
+
|
|
3
|
+
from src.error_handler import raise_error
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AstType(enum.Enum):
|
|
7
|
+
IDENTIFIER = "identifier"
|
|
8
|
+
INT_LITERAL = "int_literal"
|
|
9
|
+
NUM_LITERAL = "num_literal"
|
|
10
|
+
STR_LITERAL = "str_literal"
|
|
11
|
+
BOOL_LITERAL = "bool_literal"
|
|
12
|
+
UNARY_NOT = "unary_not"
|
|
13
|
+
UNARY_BITWISE_NOT = "unary_bitwise_not"
|
|
14
|
+
UNARY_PLUS = "unary_plus"
|
|
15
|
+
UNARY_MINUS = "unary_minus"
|
|
16
|
+
BINARY_MUL = "binary_mul"
|
|
17
|
+
BINARY_DIV = "binary_div"
|
|
18
|
+
BINARY_MOD = "binary_mod"
|
|
19
|
+
BINARY_ADD = "binary_add"
|
|
20
|
+
BINARY_SUB = "binary_sub"
|
|
21
|
+
BINARY_SHL = "binary_shl"
|
|
22
|
+
BINARY_SHR = "binary_shr"
|
|
23
|
+
BINARY_LT = "binary_lt"
|
|
24
|
+
BINARY_LTE = "binary_lte"
|
|
25
|
+
BINARY_GT = "binary_gt"
|
|
26
|
+
BINARY_GTE = "binary_gte"
|
|
27
|
+
BINARY_EQ = "binary_eq"
|
|
28
|
+
BINARY_NE = "binary_ne"
|
|
29
|
+
BINARY_BITWISE_AND = "binary_bitwise_and"
|
|
30
|
+
BINARY_BITWISE_XOR = "binary_bitwise_xor"
|
|
31
|
+
BINARY_BITWISE_OR = "binary_bitwise_or"
|
|
32
|
+
BINARY_LOGICAL_AND = "binary_logical_and"
|
|
33
|
+
BINARY_LOGICAL_OR = "binary_logical_or"
|
|
34
|
+
PROGRAM = "program"
|
|
35
|
+
ENUM_DECL = "enum_decl"
|
|
36
|
+
ENUM_ITEM = "enum_item"
|
|
37
|
+
TABLE_DECL = "table_decl"
|
|
38
|
+
FIELD_DECL = "field_decl"
|
|
39
|
+
TYPE = "type"
|
|
40
|
+
FIELD_ATTRS = "field_attrs"
|
|
41
|
+
FIELD_ATTR = "field_attr"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class ASTNode:
|
|
45
|
+
def __init__(self, node_type, position):
|
|
46
|
+
self.node_type = node_type
|
|
47
|
+
self.position = position
|
|
48
|
+
self.value: str = ""
|
|
49
|
+
self.a = None
|
|
50
|
+
self.b = None
|
|
51
|
+
self.c = None
|
|
52
|
+
self.d = None
|
|
53
|
+
self.next = None
|
|
54
|
+
|
|
55
|
+
@staticmethod
|
|
56
|
+
def create_terminal_node(type: AstType, value: str, position):
|
|
57
|
+
node = ASTNode(type, position)
|
|
58
|
+
node.value = value
|
|
59
|
+
return node
|
|
60
|
+
|
|
61
|
+
@staticmethod
|
|
62
|
+
def create_program(position):
|
|
63
|
+
return ASTNode(AstType.PROGRAM, position)
|
|
64
|
+
|
|
65
|
+
@staticmethod
|
|
66
|
+
def create_enum_decl(position):
|
|
67
|
+
return ASTNode(AstType.ENUM_DECL, position)
|
|
68
|
+
|
|
69
|
+
@staticmethod
|
|
70
|
+
def create_enum_item(position):
|
|
71
|
+
return ASTNode(AstType.ENUM_ITEM, position)
|
|
72
|
+
|
|
73
|
+
@staticmethod
|
|
74
|
+
def create_table_decl(position):
|
|
75
|
+
return ASTNode(AstType.TABLE_DECL, position)
|
|
76
|
+
|
|
77
|
+
@staticmethod
|
|
78
|
+
def create_field_decl(position):
|
|
79
|
+
return ASTNode(AstType.FIELD_DECL, position)
|
|
80
|
+
|
|
81
|
+
@staticmethod
|
|
82
|
+
def create_field_attrs(position):
|
|
83
|
+
return ASTNode(AstType.FIELD_ATTRS, position)
|
|
84
|
+
|
|
85
|
+
@staticmethod
|
|
86
|
+
def create_field_attr(position):
|
|
87
|
+
return ASTNode(AstType.FIELD_ATTR, position)
|
|
88
|
+
|
|
89
|
+
@staticmethod
|
|
90
|
+
def create_binary(op_type: AstType, left, right, position):
|
|
91
|
+
node = ASTNode(op_type, position)
|
|
92
|
+
node.a = left
|
|
93
|
+
node.b = right
|
|
94
|
+
return node
|
|
95
|
+
|
|
96
|
+
@staticmethod
|
|
97
|
+
def create_unary(op_type: AstType, operand, position):
|
|
98
|
+
node = ASTNode(op_type, position)
|
|
99
|
+
node.a = operand
|
|
100
|
+
return node
|
src/column.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
PRIMITIVE_TYPES = {'int', 'long', 'float', 'double', 'string', 'bool', 'uuid', 'datetime'}
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ColumnType:
|
|
8
|
+
def __init__(self, name: str, attrs=None, is_nullable=False, default_value=None):
|
|
9
|
+
self.name = name
|
|
10
|
+
self.is_nullable = is_nullable
|
|
11
|
+
self.attributes = attrs or {}
|
|
12
|
+
self.is_fk = False
|
|
13
|
+
self.ref_table = None
|
|
14
|
+
self.default_value = default_value
|
|
15
|
+
self.default_value_node = None
|
|
16
|
+
|
|
17
|
+
def to_csharp(self):
|
|
18
|
+
raise Exception("override")
|
|
19
|
+
|
|
20
|
+
def to_php(self):
|
|
21
|
+
raise Exception("override")
|
|
22
|
+
|
|
23
|
+
@classmethod
|
|
24
|
+
def from_ast(cls, type_node, table_names=None):
|
|
25
|
+
table_names = table_names or set()
|
|
26
|
+
type_name = type_node.value
|
|
27
|
+
attrs_node = type_node.a
|
|
28
|
+
|
|
29
|
+
attrs = {}
|
|
30
|
+
if attrs_node:
|
|
31
|
+
cur = attrs_node.a
|
|
32
|
+
while cur:
|
|
33
|
+
val = cur.b.value
|
|
34
|
+
try:
|
|
35
|
+
val = int(val)
|
|
36
|
+
except ValueError:
|
|
37
|
+
pass
|
|
38
|
+
attrs[cur.a.value] = val
|
|
39
|
+
cur = cur.next
|
|
40
|
+
|
|
41
|
+
is_nullable = type_name.endswith('?')
|
|
42
|
+
base_name = type_name[:-1] if is_nullable else type_name
|
|
43
|
+
|
|
44
|
+
if base_name in PRIMITIVE_TYPES:
|
|
45
|
+
return ColumnType(base_name, attrs, is_nullable)
|
|
46
|
+
|
|
47
|
+
col = cls(base_name, attrs, is_nullable)
|
|
48
|
+
if base_name in table_names:
|
|
49
|
+
col.is_fk = True
|
|
50
|
+
col.ref_table = base_name
|
|
51
|
+
return col
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class Int(ColumnType):
|
|
55
|
+
def __init__(self, min=None, max=None):
|
|
56
|
+
super().__init__("int", {"min": min or -2147483648, "max": max or 2147483647})
|
src/enum.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Enum:
|
|
6
|
+
def __init__(self, name, keyValue):
|
|
7
|
+
self.name = name
|
|
8
|
+
self.keyValue = keyValue
|
|
9
|
+
|
|
10
|
+
@classmethod
|
|
11
|
+
def from_ast(cls, node):
|
|
12
|
+
name = node.a.value
|
|
13
|
+
items = []
|
|
14
|
+
cur = node.b
|
|
15
|
+
while cur:
|
|
16
|
+
value = cur.b.value if cur.b else None
|
|
17
|
+
items.append((cur.a.value, value))
|
|
18
|
+
cur = cur.next
|
|
19
|
+
return cls(name, items)
|
|
20
|
+
|
|
21
|
+
|
src/error_handler.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def raise_error(file_path, file_data, message, pos):
|
|
5
|
+
PADDING = 4
|
|
6
|
+
lines = file_data.splitlines()
|
|
7
|
+
line_idx = pos.line - 1
|
|
8
|
+
col = pos.column - 1
|
|
9
|
+
|
|
10
|
+
buf = []
|
|
11
|
+
buf.append(f"Error: {message}")
|
|
12
|
+
buf.append(f" --> {file_path}:{pos.line}:{pos.column}")
|
|
13
|
+
buf.append("")
|
|
14
|
+
|
|
15
|
+
if 0 <= line_idx < len(lines):
|
|
16
|
+
context_before = 2
|
|
17
|
+
context_after = 2
|
|
18
|
+
start = max(0, line_idx - context_before)
|
|
19
|
+
end = min(len(lines), line_idx + context_after + 1)
|
|
20
|
+
|
|
21
|
+
for i in range(start, end):
|
|
22
|
+
line_num = i + 1
|
|
23
|
+
buf.append(f"{line_num:>{PADDING}} | {lines[i]}")
|
|
24
|
+
|
|
25
|
+
if i == line_idx:
|
|
26
|
+
indent = " " * (PADDING + 3)
|
|
27
|
+
col_clamped = max(0, min(col, len(lines[i])))
|
|
28
|
+
pointer = " " * col_clamped + "^"
|
|
29
|
+
remaining = len(lines[i]) - col_clamped
|
|
30
|
+
if remaining > 1:
|
|
31
|
+
pointer += "~" * min(remaining - 1, 5)
|
|
32
|
+
buf.append(f"{indent}{pointer}")
|
|
33
|
+
|
|
34
|
+
sys.stdout.write("\n".join(buf) + "\n")
|
|
35
|
+
sys.exit(1)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
GENERIC_CONTROLLER_CSHARP = """\
|
|
5
|
+
using System.Threading.Tasks;
|
|
6
|
+
using Microsoft.AspNetCore.Mvc;
|
|
7
|
+
using $$config_iservice_path$$;
|
|
8
|
+
using $$config_dto_path$$;
|
|
9
|
+
using $$config_mapper_path$$;
|
|
10
|
+
using $$config_pagination_path$$;
|
|
11
|
+
|
|
12
|
+
namespace $$config_controller_path$$;
|
|
13
|
+
|
|
14
|
+
[ApiController]
|
|
15
|
+
[Route("api/[controller]")]
|
|
16
|
+
public class GenericController<TEntity, TDto, TRequestDto, TKey> : ControllerBase
|
|
17
|
+
where TEntity : class
|
|
18
|
+
where TDto : class
|
|
19
|
+
where TRequestDto : class
|
|
20
|
+
{
|
|
21
|
+
protected readonly IGenericService<TEntity, TDto, TRequestDto, TKey> _service;
|
|
22
|
+
|
|
23
|
+
public GenericController(IGenericService<TEntity, TDto, TRequestDto, TKey> service)
|
|
24
|
+
{
|
|
25
|
+
_service = service;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
GENERIC_CONTROLLER_TEMPLATE_CSHARP = """\
|
|
31
|
+
using System.Threading.Tasks;
|
|
32
|
+
using Microsoft.AspNetCore.Mvc;
|
|
33
|
+
using $$config_iservice_path$$;
|
|
34
|
+
using $$config_dto_path$$;
|
|
35
|
+
using $$config_mapper_path$$;
|
|
36
|
+
using $$config_pagination_path$$;
|
|
37
|
+
|
|
38
|
+
namespace $$config_controller_path$$;
|
|
39
|
+
|
|
40
|
+
[ApiController]
|
|
41
|
+
[Route("api/[controller]")]
|
|
42
|
+
public class GenericController<TEntity, TDto, TKey> : GenericController<$Entity$, $TDto$, $TRequestDto$, $TKey$>
|
|
43
|
+
where TEntity : class
|
|
44
|
+
where TDto : class
|
|
45
|
+
{
|
|
46
|
+
[HttpGet("{id}", Name = "Get$Entity$ById")]
|
|
47
|
+
[Tags("$Entity$")]
|
|
48
|
+
[EndpointSummary("Retrieve by id")]
|
|
49
|
+
[EndpointDescription("Returns a single record by its unique identifier")]
|
|
50
|
+
[ProducesResponseType(typeof($TDto$), StatusCodes.Status200OK)]
|
|
51
|
+
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
52
|
+
public virtual async Task<ActionResult<$TDto$>> Show([FromRoute] $TKey$ id)
|
|
53
|
+
{
|
|
54
|
+
var result = await _service.GetByIdAsync(id);
|
|
55
|
+
return Ok(result);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
[HttpGet(Name = "Get$Entity$Paginated")]
|
|
59
|
+
[Tags("$Entity$")]
|
|
60
|
+
[EndpointSummary("Paginated list")]
|
|
61
|
+
[EndpointDescription("Returns a paginated list of records")]
|
|
62
|
+
[ProducesResponseType(typeof(PaginatedResult<$TDto$>), StatusCodes.Status200OK)]
|
|
63
|
+
public virtual async Task<ActionResult<PaginatedResult<$TDto$>>> Index([FromQuery] PaginateQuery query)
|
|
64
|
+
{
|
|
65
|
+
var result = await _service.PaginateAsync(query);
|
|
66
|
+
return Ok(result);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
[HttpPost(Name = "Create$Entity$")]
|
|
70
|
+
[Tags("$Entity$")]
|
|
71
|
+
[EndpointSummary("Create new")]
|
|
72
|
+
[EndpointDescription("Creates a new record from the provided payload")]
|
|
73
|
+
[ProducesResponseType(typeof($TDto$), StatusCodes.Status200OK)]
|
|
74
|
+
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
75
|
+
public virtual async Task<ActionResult<$TDto$>> Store([FromBody] $TRequestDto$ item)
|
|
76
|
+
{
|
|
77
|
+
var result = await _service.CreateAsync(item);
|
|
78
|
+
return Ok(result);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
[HttpPut("{id}", Name = "Update$Entity$")]
|
|
82
|
+
[Tags("$Entity$")]
|
|
83
|
+
[EndpointSummary("Update by id")]
|
|
84
|
+
[EndpointDescription("Updates an existing record identified by its id with the provided payload")]
|
|
85
|
+
[ProducesResponseType(typeof($TDto$), StatusCodes.Status200OK)]
|
|
86
|
+
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
87
|
+
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
88
|
+
public virtual async Task<ActionResult<$TDto$>> Update([FromRoute] $TKey$ id, [FromBody] $TRequestDto$ item)
|
|
89
|
+
{
|
|
90
|
+
var result = await _service.UpdateAsync(id, item);
|
|
91
|
+
return Ok(result);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
[HttpDelete("{id}", Name = "Delete$Entity$")]
|
|
95
|
+
[Tags("$Entity$")]
|
|
96
|
+
[EndpointSummary("Delete by id")]
|
|
97
|
+
[EndpointDescription("Deletes a record by its unique identifier")]
|
|
98
|
+
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
|
99
|
+
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
100
|
+
public virtual async Task<IActionResult> Destroy([FromRoute] $TKey$ id)
|
|
101
|
+
{
|
|
102
|
+
await _service.DeleteAsync(id);
|
|
103
|
+
return NoContent();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
"""
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
GENERIC_MAPPER_CSHARP = """\
|
|
2
|
+
using AutoMapper;
|
|
3
|
+
using $$config_model_path$$;
|
|
4
|
+
using $$config_dto_path$$;
|
|
5
|
+
|
|
6
|
+
namespace $$config_mapper_path$$;
|
|
7
|
+
|
|
8
|
+
public class GenericMappingProfile<TEntity, TDto> : Profile
|
|
9
|
+
where TEntity : class
|
|
10
|
+
where TDto : class
|
|
11
|
+
{
|
|
12
|
+
public GenericMappingProfile()
|
|
13
|
+
{
|
|
14
|
+
CreateMap<TEntity, TDto>().ReverseMap();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
GENERIC_MAPPER_TEMPLATE_CSHARP = """\
|
|
20
|
+
using AutoMapper;
|
|
21
|
+
using $$config_model_path$$;
|
|
22
|
+
using $$config_dto_path$$;
|
|
23
|
+
|
|
24
|
+
namespace $$config_mapper_path$$;
|
|
25
|
+
|
|
26
|
+
public class $$Entity$$MappingProfile : Profile
|
|
27
|
+
{
|
|
28
|
+
public $$Entity$$MappingProfile()
|
|
29
|
+
{
|
|
30
|
+
CreateMap<$$TRequestDto$$, $$Entity$$>();
|
|
31
|
+
CreateMap<$$Entity$$, $$TResponseDto$$>();
|
|
32
|
+
CreateMap<$$Entity$$, $$TResponseDtoSimplified$$>();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
"""
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
GENERIC_PAGINATION_CSHARP = """\
|
|
6
|
+
using System;
|
|
7
|
+
using System.Collections.Generic;
|
|
8
|
+
using System.Linq;
|
|
9
|
+
using System.Threading.Tasks;
|
|
10
|
+
using Microsoft.EntityFrameworkCore;
|
|
11
|
+
|
|
12
|
+
namespace $$config_pagination_path$$;
|
|
13
|
+
|
|
14
|
+
public class PaginatedResult<T>
|
|
15
|
+
{
|
|
16
|
+
public List<T> Items { get; set; } = new();
|
|
17
|
+
public int TotalCount { get; set; }
|
|
18
|
+
public int Page { get; set; }
|
|
19
|
+
public int Rows { get; set; }
|
|
20
|
+
public int TotalPages => (int)Math.Ceiling((double)TotalCount / Rows);
|
|
21
|
+
public bool HasPreviousPage => Page > 1;
|
|
22
|
+
public bool HasNextPage => Page < TotalPages;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public static class PaginationExtensions
|
|
26
|
+
{
|
|
27
|
+
public static async Task<PaginatedResult<T>> PaginateAsync<T>(
|
|
28
|
+
this IQueryable<T> query, int page = 1, int rows = 20)
|
|
29
|
+
{
|
|
30
|
+
var totalCount = await query.CountAsync();
|
|
31
|
+
var items = await query
|
|
32
|
+
.Skip((page - 1) * rows)
|
|
33
|
+
.Take(rows)
|
|
34
|
+
.ToListAsync();
|
|
35
|
+
return new PaginatedResult<T>
|
|
36
|
+
{
|
|
37
|
+
Items = items,
|
|
38
|
+
TotalCount = totalCount,
|
|
39
|
+
Page = page,
|
|
40
|
+
Rows = rows
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
"""
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
GENERIC_QUERY_CSHARP = """\
|
|
7
|
+
|
|
8
|
+
namespace $$config_pagination_path$$;
|
|
9
|
+
|
|
10
|
+
public class PaginateQuery
|
|
11
|
+
{
|
|
12
|
+
public string? Search { get; set; }
|
|
13
|
+
|
|
14
|
+
public int Page { get; set; } = 1;
|
|
15
|
+
|
|
16
|
+
public int Rows { get; set; } = 20;
|
|
17
|
+
}
|
|
18
|
+
"""
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
GENERIC_ISERVICE_CSHARP = """\
|
|
5
|
+
using System;
|
|
6
|
+
using System.Collections.Generic;
|
|
7
|
+
using System.Threading.Tasks;
|
|
8
|
+
using $$config_dto_path$$;
|
|
9
|
+
using $$config_pagination_path$$;
|
|
10
|
+
|
|
11
|
+
namespace $$config_iservice_path$$;
|
|
12
|
+
|
|
13
|
+
public interface IGenericService<TEntity, TDto, TRequestDto, TKey>
|
|
14
|
+
where TEntity : class
|
|
15
|
+
where TDto : class
|
|
16
|
+
where TRequestDto : class
|
|
17
|
+
{
|
|
18
|
+
public Task<TDto> GetByIdAsync(TKey id);
|
|
19
|
+
public Task<PaginatedResult<TDto>> PaginateAsync(PaginateQuery query);
|
|
20
|
+
public Task<TDto> CreateAsync(TRequestDto item);
|
|
21
|
+
public Task<TDto> UpdateAsync(TKey id, TRequestDto item);
|
|
22
|
+
public Task DeleteAsync(TKey id);
|
|
23
|
+
}
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
GENERIC_SERVICE_CSHARP = """\
|
|
28
|
+
using System;
|
|
29
|
+
using System.Collections.Generic;
|
|
30
|
+
using System.Linq;
|
|
31
|
+
using System.Threading.Tasks;
|
|
32
|
+
using AutoMapper;
|
|
33
|
+
using AutoMapper.QueryableExtensions;
|
|
34
|
+
using Microsoft.EntityFrameworkCore;
|
|
35
|
+
using $$config_iservice_path$$;
|
|
36
|
+
using $$config_model_path$$;
|
|
37
|
+
using $$config_dto_path$$;
|
|
38
|
+
using $$config_mapper_path$$;
|
|
39
|
+
using $$config_pagination_path$$;
|
|
40
|
+
|
|
41
|
+
namespace $$config_service_path$$;
|
|
42
|
+
|
|
43
|
+
public class GenericService<TEntity, TDto, TRequestDto, TKey> : IGenericService<TEntity, TDto, TRequestDto, TKey>
|
|
44
|
+
where TEntity : class
|
|
45
|
+
where TDto : class
|
|
46
|
+
where TRequestDto : class
|
|
47
|
+
{
|
|
48
|
+
protected readonly DbContext _context;
|
|
49
|
+
protected readonly DbSet<TEntity> _table;
|
|
50
|
+
protected readonly IMapper _mapper;
|
|
51
|
+
|
|
52
|
+
public GenericService(DbContext context, IMapper mapper)
|
|
53
|
+
{
|
|
54
|
+
_context = context;
|
|
55
|
+
_table = context.Set<TEntity>();
|
|
56
|
+
_mapper = mapper;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public virtual async Task<TDto> GetByIdAsync(TKey id)
|
|
60
|
+
{
|
|
61
|
+
var entity = await _table.FindAsync(id);
|
|
62
|
+
if (entity == null)
|
|
63
|
+
throw new KeyNotFoundException($"{typeof(TEntity).Name} with id {id} not found");
|
|
64
|
+
return _mapper.Map<TDto>(entity);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public virtual async Task<PaginatedResult<TDto>> PaginateAsync(PaginateQuery query)
|
|
68
|
+
{
|
|
69
|
+
var q = _table.AsQueryable();
|
|
70
|
+
var totalCount = await q.CountAsync();
|
|
71
|
+
var items = await q
|
|
72
|
+
.Skip((query.Page - 1) * query.Rows)
|
|
73
|
+
.Take(query.Rows)
|
|
74
|
+
.ProjectTo<TDto>(_mapper.ConfigurationProvider)
|
|
75
|
+
.ToListAsync();
|
|
76
|
+
return new PaginatedResult<TDto>
|
|
77
|
+
{
|
|
78
|
+
Items = items,
|
|
79
|
+
TotalCount = totalCount,
|
|
80
|
+
Page = query.Page,
|
|
81
|
+
Rows = query.Rows
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public virtual async Task<TDto> CreateAsync(TRequestDto item)
|
|
86
|
+
{
|
|
87
|
+
var entity = _mapper.Map<TEntity>(item);
|
|
88
|
+
_table.Add(entity);
|
|
89
|
+
await _context.SaveChangesAsync();
|
|
90
|
+
return _mapper.Map<TDto>(entity);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public virtual async Task<TDto> UpdateAsync(TKey id, TRequestDto item)
|
|
94
|
+
{
|
|
95
|
+
var entity = await _table.FindAsync(id);
|
|
96
|
+
if (entity == null)
|
|
97
|
+
throw new KeyNotFoundException($"{typeof(TEntity).Name} with id {id} not found");
|
|
98
|
+
_mapper.Map(item, entity);
|
|
99
|
+
await _context.SaveChangesAsync();
|
|
100
|
+
return _mapper.Map<TDto>(entity);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public virtual async Task DeleteAsync(TKey id)
|
|
104
|
+
{
|
|
105
|
+
var entity = await _table.FindAsync(id);
|
|
106
|
+
if (entity == null)
|
|
107
|
+
throw new KeyNotFoundException($"{typeof(TEntity).Name} with id {id} not found");
|
|
108
|
+
_table.Remove(entity);
|
|
109
|
+
await _context.SaveChangesAsync();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
"""
|