zrb 1.0.0b8__py3-none-any.whl → 1.0.0b10__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.
- zrb/__main__.py +3 -0
- zrb/builtin/project/add/fastapp/fastapp_task.py +1 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/.coveragerc +11 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/.gitignore +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/column/add_column_task.py +4 -4
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/config.py +5 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_task.py +108 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_util.py +67 -4
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/my_entity_service.py +5 -5
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/schema/my_entity.py +1 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/test/my_module/my_entity/test_create_my_entity.py +53 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/test/my_module/my_entity/test_delete_my_entity.py +62 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/test/my_module/my_entity/test_read_my_entity.py +65 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/test/my_module/my_entity/test_update_my_entity.py +61 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/gateway_subroute.py +57 -13
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/input.py +8 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_util.py +2 -2
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/gateway/subroute/my_module.py +6 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/module_task_definition.py +10 -6
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/task.py +65 -14
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/task_util.py +106 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/util.py +6 -86
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/base_db_repository.py +27 -11
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/base_service.py +140 -51
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/error.py +15 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/parser.py +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/config.py +22 -4
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_client.py +21 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/versions/3093c7336477_add_auth_tables.py +106 -61
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/versions/8ed025bcc845_create_permissions.py +69 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration_metadata.py +3 -4
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/route.py +15 -14
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/permission_service.py +4 -4
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/repository/role_db_repository.py +24 -5
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/role_service.py +14 -12
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_db_repository.py +134 -97
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_repository.py +28 -11
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_service.py +215 -13
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_service_factory.py +30 -2
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/subroute/auth.py +216 -41
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/util/auth.py +57 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/requirements.txt +7 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/permission.py +2 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/role.py +13 -12
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/user.py +64 -12
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/_util/access_token.py +19 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/permission/test_create_permission.py +59 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/permission/test_delete_permission.py +68 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/permission/test_read_permission.py +71 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/permission/test_update_permission.py +66 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/test_user_session.py +195 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/test_health_and_readiness.py +28 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/test_homepage.py +17 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/test_not_found_error.py +16 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test.sh +7 -0
- zrb/task/base_task.py +10 -10
- zrb/task/cmd_task.py +2 -5
- zrb/util/cmd/command.py +39 -48
- zrb/util/codemod/modification_mode.py +3 -0
- zrb/util/codemod/modify_class.py +58 -0
- zrb/util/codemod/modify_class_parent.py +68 -0
- zrb/util/codemod/modify_class_property.py +128 -0
- zrb/util/codemod/modify_dict.py +75 -0
- zrb/util/codemod/modify_function.py +65 -0
- zrb/util/codemod/modify_function_call.py +68 -0
- zrb/util/codemod/modify_method.py +88 -0
- zrb/util/codemod/{prepend_code_to_module.py → modify_module.py} +2 -3
- zrb/util/file.py +3 -2
- {zrb-1.0.0b8.dist-info → zrb-1.0.0b10.dist-info}/METADATA +2 -1
- {zrb-1.0.0b8.dist-info → zrb-1.0.0b10.dist-info}/RECORD +72 -55
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/migrate.py +0 -3
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/session.py +0 -48
- zrb/util/codemod/append_code_to_class.py +0 -35
- zrb/util/codemod/append_code_to_function.py +0 -38
- zrb/util/codemod/append_code_to_method.py +0 -55
- zrb/util/codemod/append_key_to_dict.py +0 -51
- zrb/util/codemod/append_param_to_function_call.py +0 -39
- zrb/util/codemod/prepend_parent_to_class.py +0 -38
- zrb/util/codemod/prepend_property_to_class.py +0 -55
- {zrb-1.0.0b8.dist-info → zrb-1.0.0b10.dist-info}/WHEEL +0 -0
- {zrb-1.0.0b8.dist-info → zrb-1.0.0b10.dist-info}/entry_points.txt +0 -0
@@ -3,18 +3,26 @@
|
|
3
3
|
|
4
4
|
@app.get("/api/v1/my-entities", response_model=MultipleMyEntityResponse)
|
5
5
|
async def get_my_entities(
|
6
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
6
7
|
page: int = 1,
|
7
8
|
page_size: int = 10,
|
8
9
|
sort: str | None = None,
|
9
10
|
filter: str | None = None,
|
10
11
|
) -> MultipleMyEntityResponse:
|
12
|
+
if not current_user.has_permission("my-entity:read"):
|
13
|
+
raise ForbiddenError("Access denied")
|
11
14
|
return await my_module_client.get_my_entities(
|
12
15
|
page=page, page_size=page_size, sort=sort, filter=filter
|
13
16
|
)
|
14
17
|
|
15
18
|
|
16
19
|
@app.get("/api/v1/my-entities/{my_entity_id}", response_model=MyEntityResponse)
|
17
|
-
async def get_my_entity_by_id(
|
20
|
+
async def get_my_entity_by_id(
|
21
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
22
|
+
my_entity_id: str,
|
23
|
+
) -> MyEntityResponse:
|
24
|
+
if not current_user.has_permission("my-entity:read"):
|
25
|
+
raise ForbiddenError("Access denied")
|
18
26
|
return await my_module_client.get_my_entity_by_id(my_entity_id)
|
19
27
|
|
20
28
|
|
@@ -22,9 +30,14 @@ async def get_my_entity_by_id(my_entity_id: str) -> MyEntityResponse:
|
|
22
30
|
"/api/v1/my-entities/bulk",
|
23
31
|
response_model=list[MyEntityResponse],
|
24
32
|
)
|
25
|
-
async def create_my_entity_bulk(
|
33
|
+
async def create_my_entity_bulk(
|
34
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
35
|
+
data: list[MyEntityCreate],
|
36
|
+
) -> list[MyEntityResponse]:
|
37
|
+
if not current_user.has_permission("my-entity:create"):
|
38
|
+
raise ForbiddenError("Access denied")
|
26
39
|
return await my_module_client.create_my_entity_bulk(
|
27
|
-
[row.with_audit(created_by=
|
40
|
+
[row.with_audit(created_by=current_user.id) for row in data]
|
28
41
|
)
|
29
42
|
|
30
43
|
|
@@ -32,17 +45,30 @@ async def create_my_entity_bulk(data: list[MyEntityCreate]):
|
|
32
45
|
"/api/v1/my-entities",
|
33
46
|
response_model=MyEntityResponse,
|
34
47
|
)
|
35
|
-
async def create_my_entity(
|
36
|
-
|
48
|
+
async def create_my_entity(
|
49
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
50
|
+
data: MyEntityCreate,
|
51
|
+
) -> MyEntityResponse:
|
52
|
+
if not current_user.has_permission("my-entity:create"):
|
53
|
+
raise ForbiddenError("Access denied")
|
54
|
+
return await my_module_client.create_my_entity(
|
55
|
+
data.with_audit(created_by=current_user.id)
|
56
|
+
)
|
37
57
|
|
38
58
|
|
39
59
|
@app.put(
|
40
60
|
"/api/v1/my-entities/bulk",
|
41
61
|
response_model=list[MyEntityResponse],
|
42
62
|
)
|
43
|
-
async def update_my_entity_bulk(
|
63
|
+
async def update_my_entity_bulk(
|
64
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
65
|
+
my_entity_ids: list[str],
|
66
|
+
data: MyEntityUpdate,
|
67
|
+
) -> list[MyEntityResponse]:
|
68
|
+
if not current_user.has_permission("my-entity:update"):
|
69
|
+
raise ForbiddenError("Access denied")
|
44
70
|
return await my_module_client.update_my_entity_bulk(
|
45
|
-
my_entity_ids, data.with_audit(updated_by=
|
71
|
+
my_entity_ids, data.with_audit(updated_by=current_user.id)
|
46
72
|
)
|
47
73
|
|
48
74
|
|
@@ -50,9 +76,15 @@ async def update_my_entity_bulk(my_entity_ids: list[str], data: MyEntityUpdate):
|
|
50
76
|
"/api/v1/my-entities/{my_entity_id}",
|
51
77
|
response_model=MyEntityResponse,
|
52
78
|
)
|
53
|
-
async def update_my_entity(
|
79
|
+
async def update_my_entity(
|
80
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
81
|
+
my_entity_id: str,
|
82
|
+
data: MyEntityUpdate,
|
83
|
+
) -> MyEntityResponse:
|
84
|
+
if not current_user.has_permission("my-entity:update"):
|
85
|
+
raise ForbiddenError("Access denied")
|
54
86
|
return await my_module_client.update_my_entity(
|
55
|
-
my_entity_id, data.with_audit(updated_by=
|
87
|
+
my_entity_id, data.with_audit(updated_by=current_user.id)
|
56
88
|
)
|
57
89
|
|
58
90
|
|
@@ -60,9 +92,14 @@ async def update_my_entity(my_entity_id: str, data: MyEntityUpdate):
|
|
60
92
|
"/api/v1/my-entities/bulk",
|
61
93
|
response_model=list[MyEntityResponse],
|
62
94
|
)
|
63
|
-
async def delete_my_entity_bulk(
|
95
|
+
async def delete_my_entity_bulk(
|
96
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
97
|
+
my_entity_ids: list[str],
|
98
|
+
) -> list[MyEntityResponse]:
|
99
|
+
if not current_user.has_permission("my-entity:delete"):
|
100
|
+
raise ForbiddenError("Access denied")
|
64
101
|
return await my_module_client.delete_my_entity_bulk(
|
65
|
-
my_entity_ids, deleted_by=
|
102
|
+
my_entity_ids, deleted_by=current_user.id
|
66
103
|
)
|
67
104
|
|
68
105
|
|
@@ -70,5 +107,12 @@ async def delete_my_entity_bulk(my_entity_ids: list[str]):
|
|
70
107
|
"/api/v1/my-entities/{my_entity_id}",
|
71
108
|
response_model=MyEntityResponse,
|
72
109
|
)
|
73
|
-
async def delete_my_entity(
|
74
|
-
|
110
|
+
async def delete_my_entity(
|
111
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
112
|
+
my_entity_id: str,
|
113
|
+
) -> MyEntityResponse:
|
114
|
+
if not current_user.has_permission("my-entity:delete"):
|
115
|
+
raise ForbiddenError("Access denied")
|
116
|
+
return await my_module_client.delete_my_entity(
|
117
|
+
my_entity_id, deleted_by=current_user.id
|
118
|
+
)
|
@@ -3,6 +3,14 @@ from my_app_name._zrb.util import get_existing_module_names, get_existing_schema
|
|
3
3
|
from zrb import OptionInput, StrInput
|
4
4
|
from zrb.util.string.conversion import pluralize
|
5
5
|
|
6
|
+
run_env_input = OptionInput(
|
7
|
+
name="env",
|
8
|
+
description="Running environment",
|
9
|
+
prompt="Running Environment",
|
10
|
+
options=["dev", "prod"],
|
11
|
+
default_str="prod",
|
12
|
+
)
|
13
|
+
|
6
14
|
new_module_input = StrInput(
|
7
15
|
name="module", description="Module name", prompt="New module name"
|
8
16
|
)
|
@@ -4,8 +4,8 @@ from my_app_name._zrb.config import APP_DIR
|
|
4
4
|
from my_app_name._zrb.util import get_existing_module_names
|
5
5
|
|
6
6
|
from zrb.context.any_context import AnyContext
|
7
|
-
from zrb.util.codemod.
|
8
|
-
from zrb.util.codemod.
|
7
|
+
from zrb.util.codemod.modify_dict import append_key_to_dict
|
8
|
+
from zrb.util.codemod.modify_function import append_code_to_function
|
9
9
|
from zrb.util.file import read_file, write_file
|
10
10
|
from zrb.util.string.conversion import to_kebab_case, to_pascal_case, to_snake_case
|
11
11
|
|
@@ -1,4 +1,9 @@
|
|
1
|
-
from
|
1
|
+
from typing import Annotated
|
2
|
+
|
3
|
+
from fastapi import Depends, FastAPI
|
4
|
+
from my_app_name.common.error import ForbiddenError
|
5
|
+
from my_app_name.module.gateway.util.auth import get_current_user
|
6
|
+
from my_app_name.schema.user import AuthUserResponse
|
2
7
|
|
3
8
|
|
4
9
|
def serve_my_module_route(app: FastAPI):
|
@@ -1,26 +1,30 @@
|
|
1
1
|
# 🔐 Run/Migrate My Module ==========================================================
|
2
2
|
|
3
3
|
run_my_module = app_run_group.add_task(
|
4
|
-
run_microservice("
|
4
|
+
run_microservice("my_module", 3000), alias="svc-my-module"
|
5
5
|
)
|
6
6
|
prepare_venv >> run_my_module >> run_microservices
|
7
7
|
|
8
8
|
create_my_module_migration = app_create_migration_group.add_task(
|
9
|
-
create_migration("
|
9
|
+
create_migration("my_module"), alias="my_module"
|
10
10
|
)
|
11
11
|
prepare_venv >> create_my_module_migration >> create_all_migration
|
12
12
|
|
13
|
-
migrate_monolith_my_module = migrate_module(
|
14
|
-
"my_module", "my_module", as_microservices=False
|
15
|
-
)
|
13
|
+
migrate_monolith_my_module = migrate_module("my_module", as_microservices=False)
|
16
14
|
prepare_venv >> migrate_monolith_my_module >> [migrate_monolith, run_monolith]
|
17
15
|
|
18
16
|
migrate_microservices_my_module = app_migrate_group.add_task(
|
19
|
-
migrate_module("
|
17
|
+
migrate_module("my_module", as_microservices=True),
|
20
18
|
alias="svc-my-module",
|
21
19
|
)
|
20
|
+
|
22
21
|
(
|
23
22
|
prepare_venv
|
24
23
|
>> migrate_microservices_my_module
|
25
24
|
>> [migrate_microservices, run_my_module]
|
26
25
|
)
|
26
|
+
|
27
|
+
migrate_test_my_module = migrate_module(
|
28
|
+
"my_module", as_microservices=False, additional_env_vars=TEST_ENV_VARS
|
29
|
+
)
|
30
|
+
prepare_venv >> migrate_test_my_module >> migrate_test
|
@@ -1,25 +1,66 @@
|
|
1
1
|
import os
|
2
2
|
|
3
3
|
from my_app_name._zrb.column.add_column_task import add_my_app_name_column
|
4
|
-
from my_app_name._zrb.config import
|
4
|
+
from my_app_name._zrb.config import (
|
5
|
+
ACTIVATE_VENV_SCRIPT,
|
6
|
+
APP_DIR,
|
7
|
+
MONOLITH_ENV_VARS,
|
8
|
+
TEST_ENV_VARS,
|
9
|
+
)
|
5
10
|
from my_app_name._zrb.entity.add_entity_task import add_my_app_name_entity
|
6
11
|
from my_app_name._zrb.format_task import format_my_app_name_code
|
7
12
|
from my_app_name._zrb.group import (
|
8
13
|
app_create_migration_group,
|
14
|
+
app_group,
|
9
15
|
app_migrate_group,
|
10
16
|
app_run_group,
|
11
17
|
)
|
18
|
+
from my_app_name._zrb.input import run_env_input
|
12
19
|
from my_app_name._zrb.module.add_module_task import add_my_app_name_module
|
13
|
-
from my_app_name._zrb.
|
20
|
+
from my_app_name._zrb.task_util import (
|
21
|
+
create_migration,
|
22
|
+
migrate_module,
|
23
|
+
run_microservice,
|
24
|
+
run_my_app_name,
|
25
|
+
)
|
14
26
|
from my_app_name._zrb.venv_task import prepare_venv
|
15
27
|
|
16
|
-
from zrb import CmdTask, EnvFile, EnvMap, Task
|
28
|
+
from zrb import AnyContext, CmdPath, CmdTask, EnvFile, EnvMap, Task, make_task
|
17
29
|
|
18
30
|
assert add_my_app_name_entity
|
19
31
|
assert add_my_app_name_module
|
20
32
|
assert add_my_app_name_column
|
21
33
|
assert format_my_app_name_code
|
22
34
|
|
35
|
+
# 🧪 Test ======================================================================
|
36
|
+
|
37
|
+
|
38
|
+
@make_task(
|
39
|
+
name="prepare-my-app-name-test",
|
40
|
+
)
|
41
|
+
def prepare_test(ctx: AnyContext):
|
42
|
+
db_test_path = os.path.join(APP_DIR, "test.db")
|
43
|
+
if os.path.exists(db_test_path):
|
44
|
+
ctx.print(f"Removing test db: {db_test_path}")
|
45
|
+
os.remove(db_test_path)
|
46
|
+
|
47
|
+
|
48
|
+
migrate_test = Task(name="migrate-test")
|
49
|
+
|
50
|
+
test_app = app_group.add_task(
|
51
|
+
CmdTask(
|
52
|
+
name="test-my-app-name",
|
53
|
+
description="🧪 Test My App Name",
|
54
|
+
env=EnvMap(vars=TEST_ENV_VARS),
|
55
|
+
cwd=APP_DIR,
|
56
|
+
cmd=CmdPath(os.path.join(APP_DIR, "test.sh")),
|
57
|
+
retries=0,
|
58
|
+
),
|
59
|
+
alias="test",
|
60
|
+
)
|
61
|
+
prepare_venv >> prepare_test >> migrate_test >> test_app
|
62
|
+
|
63
|
+
|
23
64
|
# 🚀 Run/Migrate All ===========================================================
|
24
65
|
|
25
66
|
run_all = app_run_group.add_task(
|
@@ -52,6 +93,7 @@ run_monolith = app_run_group.add_task(
|
|
52
93
|
CmdTask(
|
53
94
|
name="run-monolith-my-app-name",
|
54
95
|
description="🗿 Run My App Name as a monolith",
|
96
|
+
input=run_env_input,
|
55
97
|
env=[
|
56
98
|
EnvFile(path=os.path.join(APP_DIR, "template.env")),
|
57
99
|
EnvMap(vars=MONOLITH_ENV_VARS),
|
@@ -59,7 +101,7 @@ run_monolith = app_run_group.add_task(
|
|
59
101
|
cwd=APP_DIR,
|
60
102
|
cmd=[
|
61
103
|
ACTIVATE_VENV_SCRIPT,
|
62
|
-
|
104
|
+
run_my_app_name,
|
63
105
|
],
|
64
106
|
render_cmd=False,
|
65
107
|
retries=2,
|
@@ -100,40 +142,49 @@ migrate_microservices >> migrate_all
|
|
100
142
|
# 📡 Run/Migrate Gateway =======================================================
|
101
143
|
|
102
144
|
run_gateway = app_run_group.add_task(
|
103
|
-
run_microservice("gateway", 3001
|
145
|
+
run_microservice("gateway", 3001), alias="svc-gateway"
|
104
146
|
)
|
105
147
|
prepare_venv >> run_gateway >> run_microservices
|
106
148
|
|
107
149
|
create_gateway_migration = app_create_migration_group.add_task(
|
108
|
-
create_migration("gateway"
|
150
|
+
create_migration("gateway"), alias="gateway"
|
109
151
|
)
|
110
152
|
prepare_venv >> create_gateway_migration >> create_all_migration
|
111
153
|
|
112
|
-
migrate_monolith_gateway = migrate_module("gateway",
|
154
|
+
migrate_monolith_gateway = migrate_module("gateway", as_microservices=False)
|
113
155
|
prepare_venv >> migrate_monolith_gateway >> [migrate_monolith, run_monolith]
|
114
156
|
|
115
157
|
migrate_microservices_gateway = app_migrate_group.add_task(
|
116
|
-
migrate_module("gateway",
|
158
|
+
migrate_module("gateway", as_microservices=True),
|
117
159
|
alias="svc-gateway",
|
118
160
|
)
|
119
161
|
prepare_venv >> migrate_microservices_gateway >> [migrate_microservices, run_gateway]
|
120
162
|
|
163
|
+
migrate_test_gateway = migrate_module(
|
164
|
+
"gateway", as_microservices=False, additional_env_vars=TEST_ENV_VARS
|
165
|
+
)
|
166
|
+
prepare_venv >> migrate_test_gateway >> migrate_test
|
167
|
+
|
168
|
+
|
121
169
|
# 🔐 Run/Migrate Auth ==========================================================
|
122
170
|
|
123
|
-
run_auth = app_run_group.add_task(
|
124
|
-
run_microservice("auth", 3002, "auth"), alias="svc-auth"
|
125
|
-
)
|
171
|
+
run_auth = app_run_group.add_task(run_microservice("auth", 3002), alias="svc-auth")
|
126
172
|
prepare_venv >> run_auth >> run_microservices
|
127
173
|
|
128
174
|
create_auth_migration = app_create_migration_group.add_task(
|
129
|
-
create_migration("auth"
|
175
|
+
create_migration("auth"), alias="auth"
|
130
176
|
)
|
131
177
|
prepare_venv >> create_auth_migration >> create_all_migration
|
132
178
|
|
133
|
-
migrate_monolith_auth = migrate_module("auth",
|
179
|
+
migrate_monolith_auth = migrate_module("auth", as_microservices=False)
|
134
180
|
prepare_venv >> migrate_monolith_auth >> [migrate_monolith, run_monolith]
|
135
181
|
|
136
182
|
migrate_microservices_auth = app_migrate_group.add_task(
|
137
|
-
migrate_module("auth",
|
183
|
+
migrate_module("auth", as_microservices=True), alias="svc-auth"
|
138
184
|
)
|
139
185
|
prepare_venv >> migrate_microservices_auth >> [migrate_microservices, run_auth]
|
186
|
+
|
187
|
+
migrate_test_auth = migrate_module(
|
188
|
+
"auth", as_microservices=False, additional_env_vars=TEST_ENV_VARS
|
189
|
+
)
|
190
|
+
prepare_venv >> migrate_test_auth >> migrate_test
|
@@ -0,0 +1,106 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
from my_app_name._zrb.config import (
|
4
|
+
ACTIVATE_VENV_SCRIPT,
|
5
|
+
APP_DIR,
|
6
|
+
MICROSERVICES_ENV_VARS,
|
7
|
+
MONOLITH_ENV_VARS,
|
8
|
+
)
|
9
|
+
from my_app_name._zrb.input import run_env_input
|
10
|
+
from my_app_name._zrb.util import (
|
11
|
+
cd_module_script,
|
12
|
+
run_my_app_name,
|
13
|
+
set_create_migration_db_url_env,
|
14
|
+
set_env,
|
15
|
+
set_module_env,
|
16
|
+
)
|
17
|
+
|
18
|
+
from zrb import Cmd, CmdTask, EnvFile, EnvMap, StrInput, Task
|
19
|
+
from zrb.util.string.conversion import to_kebab_case, to_snake_case
|
20
|
+
|
21
|
+
|
22
|
+
def create_migration(module: str) -> Task:
|
23
|
+
name = to_kebab_case(module)
|
24
|
+
return CmdTask(
|
25
|
+
name=f"create-my-app-name-{name}-migration",
|
26
|
+
description=f"🧩 Create My App Name {name.capitalize()} DB migration",
|
27
|
+
input=StrInput(
|
28
|
+
name="message",
|
29
|
+
description="Migration message",
|
30
|
+
prompt="Migration message",
|
31
|
+
allow_empty=False,
|
32
|
+
),
|
33
|
+
env=EnvFile(path=os.path.join(APP_DIR, "template.env")),
|
34
|
+
cwd=APP_DIR,
|
35
|
+
cmd=[
|
36
|
+
ACTIVATE_VENV_SCRIPT,
|
37
|
+
set_create_migration_db_url_env(module),
|
38
|
+
set_module_env(module),
|
39
|
+
cd_module_script(module),
|
40
|
+
"alembic upgrade head",
|
41
|
+
Cmd(
|
42
|
+
"alembic revision --autogenerate -m {double_quote(ctx.input.message)}",
|
43
|
+
auto_render=True,
|
44
|
+
),
|
45
|
+
],
|
46
|
+
render_cmd=False,
|
47
|
+
retries=2,
|
48
|
+
)
|
49
|
+
|
50
|
+
|
51
|
+
def migrate_module(
|
52
|
+
module: str, as_microservices: bool, additional_env_vars: dict[str, str] = {}
|
53
|
+
) -> Task:
|
54
|
+
name = to_kebab_case(module)
|
55
|
+
env_vars = (
|
56
|
+
dict(MICROSERVICES_ENV_VARS) if as_microservices else dict(MONOLITH_ENV_VARS)
|
57
|
+
)
|
58
|
+
env_vars.update(additional_env_vars)
|
59
|
+
if as_microservices:
|
60
|
+
env_vars["MY_APP_NAME_MODULES"] = to_snake_case(module)
|
61
|
+
return CmdTask(
|
62
|
+
name=(
|
63
|
+
f"migrate-my-app-name-{name}"
|
64
|
+
if as_microservices
|
65
|
+
else f"migrate-{name}-on-monolith"
|
66
|
+
),
|
67
|
+
description=f"🧩 Run My App Name {name.capitalize()} DB migration",
|
68
|
+
env=[
|
69
|
+
EnvFile(path=os.path.join(APP_DIR, "template.env")),
|
70
|
+
EnvMap(vars=env_vars),
|
71
|
+
],
|
72
|
+
cwd=APP_DIR,
|
73
|
+
cmd=[
|
74
|
+
ACTIVATE_VENV_SCRIPT,
|
75
|
+
cd_module_script(module),
|
76
|
+
"alembic upgrade head",
|
77
|
+
],
|
78
|
+
render_cmd=False,
|
79
|
+
retries=2,
|
80
|
+
)
|
81
|
+
|
82
|
+
|
83
|
+
def run_microservice(module: str, port: int) -> Task:
|
84
|
+
name = to_kebab_case(module)
|
85
|
+
return CmdTask(
|
86
|
+
name=f"run-my-app-name-{name}",
|
87
|
+
description=f"🧩 Run My App Name {name.capitalize()}",
|
88
|
+
input=run_env_input,
|
89
|
+
env=[
|
90
|
+
EnvFile(path=os.path.join(APP_DIR, "template.env")),
|
91
|
+
EnvMap(
|
92
|
+
vars={
|
93
|
+
**MICROSERVICES_ENV_VARS,
|
94
|
+
}
|
95
|
+
),
|
96
|
+
],
|
97
|
+
cwd=APP_DIR,
|
98
|
+
cmd=[
|
99
|
+
ACTIVATE_VENV_SCRIPT,
|
100
|
+
set_env("MY_APP_NAME_MODULES", module),
|
101
|
+
set_env("MY_APP_NAME_PORT", f"{port}"),
|
102
|
+
run_my_app_name,
|
103
|
+
],
|
104
|
+
render_cmd=False,
|
105
|
+
retries=2,
|
106
|
+
)
|
@@ -1,95 +1,15 @@
|
|
1
1
|
import os
|
2
2
|
import platform
|
3
3
|
|
4
|
-
from my_app_name._zrb.config import
|
5
|
-
ACTIVATE_VENV_SCRIPT,
|
6
|
-
APP_DIR,
|
7
|
-
MICROSERVICES_ENV_VARS,
|
8
|
-
MONOLITH_ENV_VARS,
|
9
|
-
)
|
10
|
-
|
11
|
-
from zrb import Cmd, CmdTask, EnvFile, EnvMap, StrInput, Task
|
12
|
-
from zrb.util.string.conversion import double_quote, to_snake_case
|
13
|
-
|
14
|
-
|
15
|
-
def create_migration(name: str, module: str) -> Task:
|
16
|
-
return CmdTask(
|
17
|
-
name=f"create-my-app-name-{name}-migration",
|
18
|
-
description=f"🧩 Create My App Name {name.capitalize()} DB migration",
|
19
|
-
input=StrInput(
|
20
|
-
name="message",
|
21
|
-
description="Migration message",
|
22
|
-
prompt="Migration message",
|
23
|
-
allow_empty=False,
|
24
|
-
),
|
25
|
-
env=EnvFile(path=os.path.join(APP_DIR, "template.env")),
|
26
|
-
cwd=APP_DIR,
|
27
|
-
cmd=[
|
28
|
-
ACTIVATE_VENV_SCRIPT,
|
29
|
-
set_create_migration_db_url_env(module),
|
30
|
-
set_module_env(module),
|
31
|
-
cd_module_script(module),
|
32
|
-
"alembic upgrade head",
|
33
|
-
Cmd(
|
34
|
-
"alembic revision --autogenerate -m {double_quote(ctx.input.message)}",
|
35
|
-
auto_render=True,
|
36
|
-
),
|
37
|
-
],
|
38
|
-
render_cmd=False,
|
39
|
-
retries=2,
|
40
|
-
)
|
41
|
-
|
4
|
+
from my_app_name._zrb.config import APP_DIR
|
42
5
|
|
43
|
-
|
44
|
-
|
45
|
-
dict(MICROSERVICES_ENV_VARS) if as_microservices else dict(MONOLITH_ENV_VARS)
|
46
|
-
)
|
47
|
-
if as_microservices:
|
48
|
-
env_vars["MY_APP_NAME_MODULES"] = to_snake_case(module)
|
49
|
-
return CmdTask(
|
50
|
-
name=(
|
51
|
-
f"migrate-my-app-name-{name}"
|
52
|
-
if as_microservices
|
53
|
-
else f"migrate-{name}-on-monolith"
|
54
|
-
),
|
55
|
-
description=f"🧩 Run My App Name {name.capitalize()} DB migration",
|
56
|
-
env=[
|
57
|
-
EnvFile(path=os.path.join(APP_DIR, "template.env")),
|
58
|
-
EnvMap(vars=env_vars),
|
59
|
-
],
|
60
|
-
cwd=APP_DIR,
|
61
|
-
cmd=[
|
62
|
-
ACTIVATE_VENV_SCRIPT,
|
63
|
-
cd_module_script(module),
|
64
|
-
"alembic upgrade head",
|
65
|
-
],
|
66
|
-
render_cmd=False,
|
67
|
-
retries=2,
|
68
|
-
)
|
6
|
+
from zrb import AnyContext
|
7
|
+
from zrb.util.string.conversion import double_quote, to_snake_case
|
69
8
|
|
70
9
|
|
71
|
-
def
|
72
|
-
|
73
|
-
|
74
|
-
description=f"🧩 Run My App Name {name.capitalize()}",
|
75
|
-
env=[
|
76
|
-
EnvFile(path=os.path.join(APP_DIR, "template.env")),
|
77
|
-
EnvMap(
|
78
|
-
vars={
|
79
|
-
**MICROSERVICES_ENV_VARS,
|
80
|
-
}
|
81
|
-
),
|
82
|
-
],
|
83
|
-
cwd=APP_DIR,
|
84
|
-
cmd=[
|
85
|
-
ACTIVATE_VENV_SCRIPT,
|
86
|
-
set_env("MY_APP_NAME_MODULES", module),
|
87
|
-
set_env("MY_APP_NAME_PORT", f"{port}"),
|
88
|
-
'fastapi dev main.py --port "${MY_APP_NAME_PORT}"',
|
89
|
-
],
|
90
|
-
render_cmd=False,
|
91
|
-
retries=2,
|
92
|
-
)
|
10
|
+
def run_my_app_name(ctx: AnyContext) -> str:
|
11
|
+
subcommand = "dev" if ctx.input.env == "dev" else "run"
|
12
|
+
return f'fastapi {subcommand} main.py --port "${{MY_APP_NAME_PORT}}"'
|
93
13
|
|
94
14
|
|
95
15
|
def get_existing_module_names() -> list[str]:
|
@@ -122,9 +122,19 @@ class BaseDBRepository(Generic[DBModel, ResponseModel, CreateModel, UpdateModel]
|
|
122
122
|
return self._ensure_one(rows)
|
123
123
|
|
124
124
|
async def get_by_ids(self, id_list: list[str]) -> list[ResponseModel]:
|
125
|
-
|
125
|
+
rows = await self._select_to_response(
|
126
126
|
lambda q: q.where(self.db_model.id.in_(id_list))
|
127
127
|
)
|
128
|
+
# raise error if any id not in id_list
|
129
|
+
existing_id_list = [row.id for row in rows]
|
130
|
+
inexist_id_list = [id for id in id_list if id not in existing_id_list]
|
131
|
+
if len(inexist_id_list) > 0:
|
132
|
+
raise NotFoundError(
|
133
|
+
f"{self.entity_name} not found, inexist ids: {', '.join(inexist_id_list)}"
|
134
|
+
)
|
135
|
+
# sort rows
|
136
|
+
row_dict = {row.id: row for row in rows}
|
137
|
+
return [row_dict[id] for id in id_list]
|
128
138
|
|
129
139
|
async def count(self, filter: str | None = None) -> int:
|
130
140
|
count_statement = select(func.count(1)).select_from(self.db_model)
|
@@ -184,21 +194,22 @@ class BaseDBRepository(Generic[DBModel, ResponseModel, CreateModel, UpdateModel]
|
|
184
194
|
|
185
195
|
async def create_bulk(self, data_list: list[CreateModel]) -> list[DBModel]:
|
186
196
|
now = datetime.datetime.now(datetime.timezone.utc)
|
187
|
-
|
197
|
+
data_dict_list = [
|
188
198
|
self._model_to_data_dict(data, created_at=now, id=ulid.new().str)
|
189
199
|
for data in data_list
|
190
200
|
]
|
201
|
+
id_list = [data_dict["id"] for data_dict in data_dict_list]
|
191
202
|
async with self._session_scope() as session:
|
192
203
|
await self._execute_statement(
|
193
|
-
session, insert(self.db_model).values(
|
204
|
+
session, insert(self.db_model).values(data_dict_list)
|
194
205
|
)
|
195
|
-
id_list = [d["id"] for d in data_dicts]
|
196
206
|
statement = select(self.db_model).where(self.db_model.id.in_(id_list))
|
197
207
|
result = await self._execute_statement(session, statement)
|
198
|
-
|
199
|
-
self.db_model(**entity.model_dump())
|
208
|
+
row_dict = {
|
209
|
+
entity.id: self.db_model(**entity.model_dump())
|
200
210
|
for entity in result.scalars().all()
|
201
|
-
|
211
|
+
}
|
212
|
+
return [row_dict[id] for id in id_list]
|
202
213
|
|
203
214
|
async def delete(self, id: str) -> DBModel:
|
204
215
|
async with self._session_scope() as session:
|
@@ -220,11 +231,15 @@ class BaseDBRepository(Generic[DBModel, ResponseModel, CreateModel, UpdateModel]
|
|
220
231
|
await self._execute_statement(
|
221
232
|
session, delete(self.db_model).where(self.db_model.id.in_(id_list))
|
222
233
|
)
|
223
|
-
|
234
|
+
row_dict = {
|
235
|
+
entity.id: self.db_model(**entity.model_dump()) for entity in entities
|
236
|
+
}
|
237
|
+
return [row_dict[id] for id in id_list]
|
224
238
|
|
225
239
|
async def update(self, id: str, data: UpdateModel) -> DBModel:
|
226
240
|
now = datetime.datetime.now(datetime.timezone.utc)
|
227
241
|
update_data = self._model_to_data_dict(data, updated_at=now)
|
242
|
+
update_data = {k: v for k, v in update_data.items() if v is not None}
|
228
243
|
async with self._session_scope() as session:
|
229
244
|
statement = (
|
230
245
|
update(self.db_model)
|
@@ -256,7 +271,8 @@ class BaseDBRepository(Generic[DBModel, ResponseModel, CreateModel, UpdateModel]
|
|
256
271
|
result = await self._execute_statement(
|
257
272
|
session, select(self.db_model).where(self.db_model.id.in_(id_list))
|
258
273
|
)
|
259
|
-
|
260
|
-
self.db_model(**entity.model_dump())
|
274
|
+
row_dict = {
|
275
|
+
entity.id: self.db_model(**entity.model_dump())
|
261
276
|
for entity in result.scalars().all()
|
262
|
-
|
277
|
+
}
|
278
|
+
return [row_dict[id] for id in id_list]
|