zrb 1.0.0a21__py3-none-any.whl → 1.0.0b2__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/__init__.py +2 -1
- zrb/__main__.py +0 -3
- zrb/builtin/__init__.py +3 -0
- zrb/builtin/group.py +1 -0
- zrb/builtin/llm/llm_chat.py +2 -2
- zrb/builtin/llm/tool/web.py +1 -1
- zrb/builtin/project/add/fastapp/fastapp_task.py +2 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/config.py +5 -2
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_task.py +80 -20
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_util.py +150 -42
- 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 +113 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/my_entity_service_factory.py +9 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/repository/my_entity_db_repository.py +0 -10
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/repository/my_entity_repository.py +37 -16
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/repository/{factory.py → my_entity_repository_factory.py} +2 -2
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/schema/my_entity.py +16 -6
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/client_method.py +57 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/gateway_subroute.py +72 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/format_task.py +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/input.py +13 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_task.py +23 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_util.py +42 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/gateway/subroute/my_module.py +7 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/my_module_api_client.py +6 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/{any_client.py → my_module_client.py} +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/my_module_client_factory.py +11 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/my_module_direct_client.py +5 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/route.py +11 -11
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/module_task_definition.py +2 -2
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/task.py +8 -8
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/util.py +47 -20
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/app_factory.py +29 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/base_db_repository.py +185 -101
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/base_service.py +236 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/{db_engine.py → db_engine_factory.py} +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/error.py +12 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/logger_factory.py +10 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/parser_factory.py +7 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/app.py +47 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/parser.py +105 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/user_agent.py +58 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/view.py +37 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/config.py +25 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/main.py +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_api_client.py +16 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_client.py +163 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_client_factory.py +9 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_direct_client.py +15 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/versions/3093c7336477_add_auth_tables.py +160 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration_metadata.py +18 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/route.py +7 -3
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/permission_service.py +117 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/permission_service_factory.py +11 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/repository/permission_db_repository.py +26 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/repository/permission_repository.py +61 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/repository/permission_repository_factory.py +13 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/repository/role_db_repository.py +75 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/repository/role_repository.py +59 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/repository/role_repository_factory.py +13 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/role_service.py +105 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/role_service_factory.py +7 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_db_repository.py +42 -13
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_repository.py +38 -17
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_repository_factory.py +2 -2
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_service.py +105 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_service_factory.py +7 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/route.py +43 -14
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/subroute/auth.py +198 -28
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/util/view.py +74 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/error.html +6 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/homepage.html +6 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/images/android-chrome-192x192.png +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/images/android-chrome-512x512.png +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/images/favicon-32x32.png +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.amber.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.blue.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.cyan.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.fuchsia.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.green.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.grey.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.indigo.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.jade.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.lime.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.orange.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.pink.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.pumpkin.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.purple.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.red.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.sand.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.slate.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.violet.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.yellow.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.zinc.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/template/default.html +34 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/requirements.txt +1 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/permission.py +17 -5
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/role.py +50 -4
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/session.py +52 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/user.py +30 -5
- zrb/builtin/python.py +1 -1
- zrb/builtin/random.py +61 -0
- zrb/cmd/cmd_val.py +6 -5
- zrb/content_transformer/any_content_transformer.py +7 -0
- zrb/content_transformer/content_transformer.py +6 -0
- zrb/runner/cli.py +14 -7
- zrb/runner/web_app.py +28 -280
- zrb/runner/web_config/config.py +91 -0
- zrb/runner/web_config/config_factory.py +26 -0
- zrb/runner/web_route/docs_route.py +17 -0
- zrb/runner/web_route/error_page/serve_default_404.py +28 -0
- zrb/runner/{web_controller/error_page/controller.py → web_route/error_page/show_error_page.py} +2 -2
- zrb/runner/{web_controller → web_route}/error_page/view.html +5 -0
- zrb/runner/web_route/home_page/home_page_route.py +51 -0
- zrb/runner/web_route/login_api_route.py +31 -0
- zrb/runner/web_route/login_page/login_page_route.py +39 -0
- zrb/runner/web_route/logout_api_route.py +18 -0
- zrb/runner/web_route/logout_page/logout_page_route.py +40 -0
- zrb/runner/{web_controller/group_info_page/controller.py → web_route/node_page/group/show_group_page.py} +3 -3
- zrb/runner/web_route/node_page/node_page_route.py +50 -0
- zrb/runner/{web_controller/session_page/controller.py → web_route/node_page/task/show_task_page.py} +3 -3
- zrb/runner/web_route/refresh_token_api_route.py +38 -0
- zrb/runner/web_route/static/static_route.py +44 -0
- zrb/runner/web_route/task_input_api_route.py +47 -0
- zrb/runner/web_route/task_session_api_route.py +102 -0
- zrb/runner/web_schema/session.py +5 -0
- zrb/runner/web_schema/token.py +11 -0
- zrb/runner/web_schema/user.py +32 -0
- zrb/runner/web_util/cookie.py +29 -0
- zrb/runner/{web_util.py → web_util/html.py} +1 -23
- zrb/runner/web_util/token.py +72 -0
- zrb/runner/web_util/user.py +63 -0
- zrb/session/session.py +6 -4
- zrb/session_state_logger/{default_session_state_logger.py → session_state_logger_factory.py} +1 -1
- zrb/task/base_task.py +53 -6
- zrb/task/base_trigger.py +2 -0
- zrb/task/cmd_task.py +9 -5
- zrb/task/http_check.py +2 -0
- zrb/task/llm_task.py +2 -0
- zrb/task/make_task.py +2 -0
- zrb/task/rsync_task.py +2 -0
- zrb/task/scaffolder.py +8 -5
- zrb/task/scheduler.py +2 -0
- zrb/task/tcp_check.py +2 -0
- zrb/task_status/task_status.py +4 -3
- zrb/util/cmd/command.py +1 -0
- zrb/util/file.py +7 -1
- {zrb-1.0.0a21.dist-info → zrb-1.0.0b2.dist-info}/METADATA +1 -1
- zrb-1.0.0b2.dist-info/RECORD +307 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/any_client_method.py +0 -27
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/my_entity_usecase.py +0 -65
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/api_client.py +0 -6
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/direct_client.py +0 -6
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/factory.py +0 -9
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/app.py +0 -20
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/base_usecase.py +0 -245
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/any_client.py +0 -33
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/api_client.py +0 -7
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/direct_client.py +0 -6
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/factory.py +0 -9
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/versions/3093c7336477_add_user_table.py +0 -37
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_usecase.py +0 -53
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_usecase_factory.py +0 -6
- zrb/runner/web_config.py +0 -274
- zrb/runner/web_controller/home_page/controller.py +0 -33
- zrb/runner/web_controller/login_page/controller.py +0 -25
- zrb/runner/web_controller/logout_page/controller.py +0 -26
- zrb-1.0.0a21.dist-info/RECORD +0 -244
- /zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/column/{create_column_task.py → add_column_task.py} +0 -0
- /zrb/{runner/web_controller → builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission}/__init__.py +0 -0
- /zrb/{runner/web_controller/group_info_page → builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role}/__init__.py +0 -0
- /zrb/runner/{web_controller/home_page → web_route}/__init__.py +0 -0
- /zrb/runner/{web_controller/session_page → web_route/home_page}/__init__.py +0 -0
- /zrb/runner/{web_controller → web_route}/home_page/view.html +0 -0
- /zrb/runner/{web_controller → web_route}/login_page/view.html +0 -0
- /zrb/runner/{web_controller → web_route}/logout_page/view.html +0 -0
- /zrb/runner/{web_controller/group_info_page → web_route/node_page/group}/view.html +0 -0
- /zrb/runner/{web_controller/session_page → web_route/node_page/task}/partial/input.html +0 -0
- /zrb/runner/{web_controller/session_page → web_route/node_page/task}/view.html +0 -0
- /zrb/runner/{refresh-token.template.js → web_route/static/refresh-token.template.js} +0 -0
- /zrb/runner/{web_controller/static → web_route/static/resources}/common.css +0 -0
- /zrb/runner/{web_controller/static → web_route/static/resources}/favicon-32x32.png +0 -0
- /zrb/runner/{web_controller/static → web_route/static/resources}/login/event.js +0 -0
- /zrb/runner/{web_controller/static → web_route/static/resources}/logout/event.js +0 -0
- /zrb/runner/{web_controller/static → web_route/static/resources}/pico.min.css +0 -0
- /zrb/runner/{web_controller/static → web_route/static/resources}/session/common-util.js +0 -0
- /zrb/runner/{web_controller/static → web_route/static/resources}/session/current-session.js +0 -0
- /zrb/runner/{web_controller/static → web_route/static/resources}/session/event.js +0 -0
- /zrb/runner/{web_controller/static → web_route/static/resources}/session/past-session.js +0 -0
- {zrb-1.0.0a21.dist-info → zrb-1.0.0b2.dist-info}/WHEEL +0 -0
- {zrb-1.0.0a21.dist-info → zrb-1.0.0b2.dist-info}/entry_points.txt +0 -0
@@ -1,7 +1,7 @@
|
|
1
1
|
# 🔐 Run/Migrate My Module ==========================================================
|
2
2
|
|
3
3
|
run_my_module = app_run_group.add_task(
|
4
|
-
run_microservice("my-module", 3000, "my_module"), alias="
|
4
|
+
run_microservice("my-module", 3000, "my_module"), alias="svc-my_module"
|
5
5
|
)
|
6
6
|
prepare_venv >> run_my_module >> run_microservices
|
7
7
|
|
@@ -17,7 +17,7 @@ prepare_venv >> migrate_monolith_my_module >> [migrate_monolith, run_monolith]
|
|
17
17
|
|
18
18
|
migrate_microservices_my_module = app_migrate_group.add_task(
|
19
19
|
migrate_module("my-module", "my_module", as_microservices=True),
|
20
|
-
alias="
|
20
|
+
alias="svc-my-module",
|
21
21
|
)
|
22
22
|
(
|
23
23
|
prepare_venv
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import os
|
2
2
|
|
3
|
-
from my_app_name._zrb.column.
|
4
|
-
from my_app_name._zrb.config import ACTIVATE_VENV_SCRIPT, APP_DIR
|
3
|
+
from my_app_name._zrb.column.add_column_task import add_my_app_name_column
|
4
|
+
from my_app_name._zrb.config import ACTIVATE_VENV_SCRIPT, APP_DIR, MONOLITH_ENV_VARS
|
5
5
|
from my_app_name._zrb.entity.add_entity_task import add_my_app_name_entity
|
6
6
|
from my_app_name._zrb.format_task import format_my_app_name_code
|
7
7
|
from my_app_name._zrb.group import (
|
@@ -13,7 +13,7 @@ from my_app_name._zrb.module.add_module_task import add_my_app_name_module
|
|
13
13
|
from my_app_name._zrb.util import create_migration, migrate_module, run_microservice
|
14
14
|
from my_app_name._zrb.venv_task import prepare_venv
|
15
15
|
|
16
|
-
from zrb import CmdTask,
|
16
|
+
from zrb import CmdTask, EnvFile, EnvMap, Task
|
17
17
|
|
18
18
|
assert add_my_app_name_entity
|
19
19
|
assert add_my_app_name_module
|
@@ -54,7 +54,7 @@ run_monolith = app_run_group.add_task(
|
|
54
54
|
description="🗿 Run My App Name as a monolith",
|
55
55
|
env=[
|
56
56
|
EnvFile(path=os.path.join(APP_DIR, "template.env")),
|
57
|
-
|
57
|
+
EnvMap(vars=MONOLITH_ENV_VARS),
|
58
58
|
],
|
59
59
|
cwd=APP_DIR,
|
60
60
|
cmd=[
|
@@ -100,7 +100,7 @@ migrate_microservices >> migrate_all
|
|
100
100
|
# 📡 Run/Migrate Gateway =======================================================
|
101
101
|
|
102
102
|
run_gateway = app_run_group.add_task(
|
103
|
-
run_microservice("gateway", 3001, "gateway"), alias="
|
103
|
+
run_microservice("gateway", 3001, "gateway"), alias="svc-gateway"
|
104
104
|
)
|
105
105
|
prepare_venv >> run_gateway >> run_microservices
|
106
106
|
|
@@ -114,14 +114,14 @@ prepare_venv >> migrate_monolith_gateway >> [migrate_monolith, run_monolith]
|
|
114
114
|
|
115
115
|
migrate_microservices_gateway = app_migrate_group.add_task(
|
116
116
|
migrate_module("gateway", "gateway", as_microservices=True),
|
117
|
-
alias="
|
117
|
+
alias="svc-gateway",
|
118
118
|
)
|
119
119
|
prepare_venv >> migrate_microservices_gateway >> [migrate_microservices, run_gateway]
|
120
120
|
|
121
121
|
# 🔐 Run/Migrate Auth ==========================================================
|
122
122
|
|
123
123
|
run_auth = app_run_group.add_task(
|
124
|
-
run_microservice("auth", 3002, "auth"), alias="
|
124
|
+
run_microservice("auth", 3002, "auth"), alias="svc-auth"
|
125
125
|
)
|
126
126
|
prepare_venv >> run_auth >> run_microservices
|
127
127
|
|
@@ -134,6 +134,6 @@ migrate_monolith_auth = migrate_module("auth", "auth", as_microservices=False)
|
|
134
134
|
prepare_venv >> migrate_monolith_auth >> [migrate_monolith, run_monolith]
|
135
135
|
|
136
136
|
migrate_microservices_auth = app_migrate_group.add_task(
|
137
|
-
migrate_module("auth", "auth", as_microservices=True), alias="
|
137
|
+
migrate_module("auth", "auth", as_microservices=True), alias="svc-auth"
|
138
138
|
)
|
139
139
|
prepare_venv >> migrate_microservices_auth >> [migrate_microservices, run_auth]
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import os
|
2
|
+
import platform
|
2
3
|
|
3
4
|
from my_app_name._zrb.config import (
|
4
5
|
ACTIVATE_VENV_SCRIPT,
|
@@ -8,6 +9,7 @@ from my_app_name._zrb.config import (
|
|
8
9
|
)
|
9
10
|
|
10
11
|
from zrb import Cmd, CmdTask, EnvFile, EnvMap, StrInput, Task
|
12
|
+
from zrb.util.string.conversion import double_quote, to_snake_case
|
11
13
|
|
12
14
|
|
13
15
|
def create_migration(name: str, module: str) -> Task:
|
@@ -20,19 +22,13 @@ def create_migration(name: str, module: str) -> Task:
|
|
20
22
|
prompt="Migration message",
|
21
23
|
allow_empty=False,
|
22
24
|
),
|
23
|
-
env=
|
24
|
-
EnvFile(path=os.path.join(APP_DIR, "template.env")),
|
25
|
-
EnvMap(
|
26
|
-
vars={
|
27
|
-
"APP_DB_URL": f"sqlite:///{APP_DIR}/.migration.{module}.db",
|
28
|
-
"MY_APP_NAME_MODULES": f"{module}",
|
29
|
-
}
|
30
|
-
),
|
31
|
-
],
|
25
|
+
env=EnvFile(path=os.path.join(APP_DIR, "template.env")),
|
32
26
|
cwd=APP_DIR,
|
33
27
|
cmd=[
|
34
28
|
ACTIVATE_VENV_SCRIPT,
|
35
|
-
|
29
|
+
set_create_migration_db_url_env(module),
|
30
|
+
set_module_env(module),
|
31
|
+
cd_module_script(module),
|
36
32
|
"alembic upgrade head",
|
37
33
|
Cmd(
|
38
34
|
"alembic revision --autogenerate -m {double_quote(ctx.input.message)}",
|
@@ -45,7 +41,11 @@ def create_migration(name: str, module: str) -> Task:
|
|
45
41
|
|
46
42
|
|
47
43
|
def migrate_module(name: str, module: str, as_microservices: bool) -> Task:
|
48
|
-
env_vars =
|
44
|
+
env_vars = (
|
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
49
|
return CmdTask(
|
50
50
|
name=(
|
51
51
|
f"migrate-my-app-name-{name}"
|
@@ -55,17 +55,12 @@ def migrate_module(name: str, module: str, as_microservices: bool) -> Task:
|
|
55
55
|
description=f"🧩 Run My App Name {name.capitalize()} DB migration",
|
56
56
|
env=[
|
57
57
|
EnvFile(path=os.path.join(APP_DIR, "template.env")),
|
58
|
-
EnvMap(
|
59
|
-
vars={
|
60
|
-
**env_vars,
|
61
|
-
"MY_APP_NAME_MODULES": f"{module}",
|
62
|
-
}
|
63
|
-
),
|
58
|
+
EnvMap(vars=env_vars),
|
64
59
|
],
|
65
60
|
cwd=APP_DIR,
|
66
61
|
cmd=[
|
67
62
|
ACTIVATE_VENV_SCRIPT,
|
68
|
-
|
63
|
+
cd_module_script(module),
|
69
64
|
"alembic upgrade head",
|
70
65
|
],
|
71
66
|
render_cmd=False,
|
@@ -82,14 +77,14 @@ def run_microservice(name: str, port: int, module: str) -> Task:
|
|
82
77
|
EnvMap(
|
83
78
|
vars={
|
84
79
|
**MICROSERVICES_ENV_VARS,
|
85
|
-
"MY_APP_NAME_PORT": f"{port}",
|
86
|
-
"MY_APP_NAME_MODULES": f"{module}",
|
87
80
|
}
|
88
81
|
),
|
89
82
|
],
|
90
83
|
cwd=APP_DIR,
|
91
84
|
cmd=[
|
92
85
|
ACTIVATE_VENV_SCRIPT,
|
86
|
+
set_env("MY_APP_NAME_MODULES", module),
|
87
|
+
set_env("MY_APP_NAME_PORT", f"{port}"),
|
93
88
|
'fastapi dev main.py --port "${MY_APP_NAME_PORT}"',
|
94
89
|
],
|
95
90
|
render_cmd=False,
|
@@ -109,3 +104,35 @@ def get_existing_schema_names() -> list[str]:
|
|
109
104
|
for entry in os.scandir(module_dir_path)
|
110
105
|
if entry.is_file() and entry.name.endswith(".py")
|
111
106
|
]
|
107
|
+
|
108
|
+
|
109
|
+
def set_create_migration_db_url_env(module_name: str) -> str:
|
110
|
+
return set_env(
|
111
|
+
"MY_APP_NAME_DB_URL",
|
112
|
+
f"sqlite:///{APP_DIR}/.migration.{to_snake_case(module_name)}.db",
|
113
|
+
)
|
114
|
+
|
115
|
+
|
116
|
+
def set_module_env(module_name: str) -> str:
|
117
|
+
return (set_env("MY_APP_NAME_MODULES", to_snake_case(module_name)),)
|
118
|
+
|
119
|
+
|
120
|
+
def cd_module_script(module_name: str) -> str:
|
121
|
+
module_dir_path = os.path.join(APP_DIR, "module", to_snake_case(module_name))
|
122
|
+
return f"cd {module_dir_path}"
|
123
|
+
|
124
|
+
|
125
|
+
def set_env(var_name: str, var_value: str) -> str:
|
126
|
+
"""
|
127
|
+
Generates a script to set an environment variable depending on the OS.
|
128
|
+
:param var_name: Name of the environment variable.
|
129
|
+
:param var_value: Value of the environment variable.
|
130
|
+
:return: A string containing the appropriate script.
|
131
|
+
"""
|
132
|
+
if platform.system() == "Windows":
|
133
|
+
# PowerShell script for Windows
|
134
|
+
script = f'[Environment]::SetEnvironmentVariable({double_quote(var_name)}, {double_quote(var_value)}, "User")' # noqa
|
135
|
+
else:
|
136
|
+
# Bash script for Unix-like systems
|
137
|
+
script = f"export {var_name}={double_quote(var_value)}"
|
138
|
+
return script
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
from fastapi import FastAPI
|
4
|
+
from my_app_name.common.db_engine_factory import db_engine
|
5
|
+
from my_app_name.common.util.app import (
|
6
|
+
create_default_app_lifespan,
|
7
|
+
get_default_app_title,
|
8
|
+
serve_docs,
|
9
|
+
serve_static_dir,
|
10
|
+
)
|
11
|
+
from my_app_name.config import (
|
12
|
+
APP_GATEWAY_FAVICON_PATH,
|
13
|
+
APP_GATEWAY_TITLE,
|
14
|
+
APP_GATEWAY_VIEW_PATH,
|
15
|
+
APP_MODE,
|
16
|
+
APP_MODULES,
|
17
|
+
APP_VERSION,
|
18
|
+
)
|
19
|
+
|
20
|
+
app_title = get_default_app_title(APP_GATEWAY_TITLE, mode=APP_MODE, modules=APP_MODULES)
|
21
|
+
app = FastAPI(
|
22
|
+
title=app_title,
|
23
|
+
version=APP_VERSION,
|
24
|
+
lifespan=create_default_app_lifespan(db_engine),
|
25
|
+
docs_url=None,
|
26
|
+
)
|
27
|
+
|
28
|
+
serve_static_dir(app, os.path.join(APP_GATEWAY_VIEW_PATH, "static"))
|
29
|
+
serve_docs(app, app_title=app_title, favicon_url=APP_GATEWAY_FAVICON_PATH)
|
@@ -1,12 +1,17 @@
|
|
1
|
+
import datetime
|
2
|
+
from contextlib import asynccontextmanager
|
1
3
|
from typing import Any, Callable, Generic, Type, TypeVar
|
2
4
|
|
3
|
-
|
4
|
-
from
|
5
|
+
import ulid
|
6
|
+
from my_app_name.common.error import InvalidValueError, NotFoundError
|
7
|
+
from my_app_name.common.parser_factory import parse_filter_param, parse_sort_param
|
8
|
+
from sqlalchemy import Engine, delete, func, insert, select, update
|
5
9
|
from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession
|
6
|
-
from
|
10
|
+
from sqlalchemy.sql import Select
|
11
|
+
from sqlmodel import Session, SQLModel
|
7
12
|
|
8
13
|
DBModel = TypeVar("DBModel", bound=SQLModel)
|
9
|
-
ResponseModel = TypeVar("
|
14
|
+
ResponseModel = TypeVar("ResponseModel", bound=SQLModel)
|
10
15
|
CreateModel = TypeVar("CreateModel", bound=SQLModel)
|
11
16
|
UpdateModel = TypeVar("UpdateModel", bound=SQLModel)
|
12
17
|
|
@@ -23,112 +28,191 @@ class BaseDBRepository(Generic[DBModel, ResponseModel, CreateModel, UpdateModel]
|
|
23
28
|
self.engine = engine
|
24
29
|
self.is_async = isinstance(engine, AsyncEngine)
|
25
30
|
|
26
|
-
def
|
27
|
-
return self.
|
31
|
+
def _select(self) -> Select:
|
32
|
+
return select(self.db_model)
|
28
33
|
|
29
|
-
|
30
|
-
|
31
|
-
for key, preprocessor in self.column_preprocessors.items():
|
32
|
-
if key in data_dict:
|
33
|
-
data_dict[key] = preprocessor(data_dict[key])
|
34
|
-
db_instance = self.db_model(**data_dict)
|
35
|
-
if self.is_async:
|
36
|
-
async with AsyncSession(self.engine) as session:
|
37
|
-
session.add(db_instance)
|
38
|
-
await session.commit()
|
39
|
-
await session.refresh(db_instance)
|
40
|
-
else:
|
41
|
-
with Session(self.engine) as session:
|
42
|
-
session.add(db_instance)
|
43
|
-
session.commit()
|
44
|
-
session.refresh(db_instance)
|
45
|
-
return self._to_response(db_instance)
|
34
|
+
def _rows_to_responses(self, rows: list[tuple[Any]]) -> list[ResponseModel]:
|
35
|
+
return [self.response_model.model_validate(row[0]) for row in rows]
|
46
36
|
|
47
|
-
|
48
|
-
if
|
49
|
-
async with AsyncSession(self.engine) as session:
|
50
|
-
db_instance = await session.get(self.db_model, item_id)
|
51
|
-
else:
|
52
|
-
with Session(self.engine) as session:
|
53
|
-
db_instance = session.get(self.db_model, item_id)
|
54
|
-
if not db_instance:
|
37
|
+
def _ensure_one(self, responses: list[ResponseModel]) -> ResponseModel:
|
38
|
+
if not responses:
|
55
39
|
raise NotFoundError(f"{self.entity_name} not found")
|
56
|
-
|
40
|
+
if len(responses) > 1:
|
41
|
+
raise InvalidValueError(f"Duplicate {self.entity_name}")
|
42
|
+
return responses[0]
|
57
43
|
|
58
|
-
|
59
|
-
|
60
|
-
statement = select(self.db_model).offset(offset).limit(page_size)
|
44
|
+
@asynccontextmanager
|
45
|
+
async def _session_scope(self):
|
61
46
|
if self.is_async:
|
62
47
|
async with AsyncSession(self.engine) as session:
|
63
|
-
|
64
|
-
|
48
|
+
async with session.begin():
|
49
|
+
yield session
|
65
50
|
else:
|
66
51
|
with Session(self.engine) as session:
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
async def
|
71
|
-
update_data = data.model_dump(exclude_unset=True)
|
72
|
-
for key, value in update_data.items():
|
73
|
-
if key in self.column_preprocessors:
|
74
|
-
update_data[key] = self.column_preprocessors[key](value)
|
75
|
-
if self.is_async:
|
76
|
-
async with AsyncSession(self.engine) as session:
|
77
|
-
db_instance = await session.get(self.db_model, item_id)
|
78
|
-
if not db_instance:
|
79
|
-
raise NotFoundError(f"{self.entity_name} not found")
|
80
|
-
for key, value in update_data.items():
|
81
|
-
setattr(db_instance, key, value)
|
82
|
-
session.add(db_instance)
|
83
|
-
await session.commit()
|
84
|
-
await session.refresh(db_instance)
|
85
|
-
else:
|
86
|
-
with Session(self.engine) as session:
|
87
|
-
db_instance = session.get(self.db_model, item_id)
|
88
|
-
if not db_instance:
|
89
|
-
raise NotFoundError(f"{self.entity_name} not found")
|
90
|
-
for key, value in update_data.items():
|
91
|
-
setattr(db_instance, key, value)
|
92
|
-
session.add(db_instance)
|
93
|
-
session.commit()
|
94
|
-
session.refresh(db_instance)
|
95
|
-
return self._to_response(db_instance)
|
96
|
-
|
97
|
-
async def delete(self, item_id: str) -> ResponseModel:
|
52
|
+
with session.begin():
|
53
|
+
yield session
|
54
|
+
|
55
|
+
async def _commit(self, session: Session | AsyncSession):
|
98
56
|
if self.is_async:
|
99
|
-
|
100
|
-
db_instance = await session.get(self.db_model, item_id)
|
101
|
-
if not db_instance:
|
102
|
-
raise NotFoundError(f"{self.entity_name} not found")
|
103
|
-
await session.delete(db_instance)
|
104
|
-
await session.commit()
|
57
|
+
await session.commit()
|
105
58
|
else:
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
raise NotFoundError(f"{self.entity_name} not found")
|
110
|
-
session.delete(db_instance)
|
111
|
-
session.commit()
|
112
|
-
return self._to_response(db_instance)
|
113
|
-
|
114
|
-
async def create_bulk(self, data_list: list[CreateModel]) -> list[ResponseModel]:
|
115
|
-
db_instances = []
|
116
|
-
for data in data_list:
|
117
|
-
data_dict = data.model_dump(exclude_unset=True)
|
118
|
-
for key, preprocessor in self.column_preprocessors.items():
|
119
|
-
if key in data_dict:
|
120
|
-
data_dict[key] = preprocessor(data_dict[key])
|
121
|
-
db_instances.append(self.db_model(**data_dict))
|
59
|
+
session.commit()
|
60
|
+
|
61
|
+
async def _execute_statement(self, session, statement: Any) -> Any:
|
122
62
|
if self.is_async:
|
123
|
-
|
124
|
-
session.add_all(db_instances)
|
125
|
-
await session.commit()
|
126
|
-
for instance in db_instances:
|
127
|
-
await session.refresh(instance)
|
63
|
+
return await session.execute(statement)
|
128
64
|
else:
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
65
|
+
return session.execute(statement)
|
66
|
+
|
67
|
+
async def get_by_id(self, id: str) -> ResponseModel:
|
68
|
+
statement = self._select().where(self.db_model.id == id)
|
69
|
+
async with self._session_scope() as session:
|
70
|
+
result = await self._execute_statement(session, statement)
|
71
|
+
responses = self._rows_to_responses(result.all())
|
72
|
+
return self._ensure_one(responses)
|
73
|
+
|
74
|
+
async def get_by_ids(self, id_list: list[str]) -> list[ResponseModel]:
|
75
|
+
statement = self._select().where(self.db_model.id.in_(id_list))
|
76
|
+
async with self._session_scope() as session:
|
77
|
+
result = await self._execute_statement(session, statement)
|
78
|
+
return [
|
79
|
+
self.db_model(**entity.model_dump())
|
80
|
+
for entity in result.scalars().all()
|
81
|
+
]
|
82
|
+
|
83
|
+
async def count(self, filter: str | None = None) -> int:
|
84
|
+
count_statement = select(func.count(1)).select_from(self.db_model)
|
85
|
+
if filter:
|
86
|
+
filter_param = parse_filter_param(self.db_model, filter)
|
87
|
+
count_statement = count_statement.where(*filter_param)
|
88
|
+
async with self._session_scope() as session:
|
89
|
+
result = await self._execute_statement(session, count_statement)
|
90
|
+
return result.scalar_one()
|
91
|
+
|
92
|
+
async def get(
|
93
|
+
self,
|
94
|
+
page: int = 1,
|
95
|
+
page_size: int = 10,
|
96
|
+
filter: str | None = None,
|
97
|
+
sort: str | None = None,
|
98
|
+
) -> list[ResponseModel]:
|
99
|
+
offset = (page - 1) * page_size
|
100
|
+
statement = self._select().offset(offset).limit(page_size)
|
101
|
+
if filter:
|
102
|
+
filter_param = parse_filter_param(self.db_model, filter)
|
103
|
+
statement = statement.where(*filter_param)
|
104
|
+
if sort:
|
105
|
+
sort_param = parse_sort_param(self.db_model, sort)
|
106
|
+
statement = statement.order_by(*sort_param)
|
107
|
+
async with self._session_scope() as session:
|
108
|
+
result = await self._execute_statement(session, statement)
|
109
|
+
return [
|
110
|
+
self.db_model(**entity.model_dump())
|
111
|
+
for entity in result.scalars().all()
|
112
|
+
]
|
113
|
+
|
114
|
+
def _model_to_data_dict(
|
115
|
+
self, data: SQLModel, **additional_data: Any
|
116
|
+
) -> dict[str, Any]:
|
117
|
+
data_dict = data.model_dump(exclude_unset=True)
|
118
|
+
data_dict.update(additional_data)
|
119
|
+
for key, preprocessor in self.column_preprocessors.items():
|
120
|
+
if key not in data_dict:
|
121
|
+
continue
|
122
|
+
if not hasattr(self.db_model, key):
|
123
|
+
raise InvalidValueError(f"Invalid {self.entity_name} property: {key}")
|
124
|
+
data_dict[key] = preprocessor(data_dict[key])
|
125
|
+
return data_dict
|
126
|
+
|
127
|
+
async def create(self, data: CreateModel) -> DBModel:
|
128
|
+
now = datetime.datetime.now(datetime.timezone.utc)
|
129
|
+
data_dict = self._model_to_data_dict(data, created_at=now, id=ulid.new().str)
|
130
|
+
async with self._session_scope() as session:
|
131
|
+
await self._execute_statement(
|
132
|
+
session, insert(self.db_model).values(**data_dict)
|
133
|
+
)
|
134
|
+
statement = select(self.db_model).where(self.db_model.id == data_dict["id"])
|
135
|
+
result = await self._execute_statement(session, statement)
|
136
|
+
created_entity = result.scalar_one_or_none()
|
137
|
+
if created_entity is None:
|
138
|
+
raise NotFoundError(f"{self.entity_name} not found after creation")
|
139
|
+
return self.db_model(**created_entity.model_dump())
|
140
|
+
|
141
|
+
async def create_bulk(self, data_list: list[CreateModel]) -> list[DBModel]:
|
142
|
+
now = datetime.datetime.now(datetime.timezone.utc)
|
143
|
+
data_dicts = [
|
144
|
+
self._model_to_data_dict(data, created_at=now, id=ulid.new().str)
|
145
|
+
for data in data_list
|
146
|
+
]
|
147
|
+
async with self._session_scope() as session:
|
148
|
+
await self._execute_statement(
|
149
|
+
session, insert(self.db_model).values(data_dicts)
|
150
|
+
)
|
151
|
+
id_list = [d["id"] for d in data_dicts]
|
152
|
+
statement = select(self.db_model).where(self.db_model.id.in_(id_list))
|
153
|
+
result = await self._execute_statement(session, statement)
|
154
|
+
return [
|
155
|
+
self.db_model(**entity.model_dump())
|
156
|
+
for entity in result.scalars().all()
|
157
|
+
]
|
158
|
+
|
159
|
+
async def delete(self, id: str) -> DBModel:
|
160
|
+
async with self._session_scope() as session:
|
161
|
+
statement = select(self.db_model).where(self.db_model.id == id)
|
162
|
+
result = await self._execute_statement(session, statement)
|
163
|
+
entity = result.scalar_one_or_none()
|
164
|
+
if not entity:
|
165
|
+
raise NotFoundError(f"{self.entity_name} not found")
|
166
|
+
await self._execute_statement(
|
167
|
+
session, delete(self.db_model).where(self.db_model.id == id)
|
168
|
+
)
|
169
|
+
return self.db_model(**entity.model_dump())
|
170
|
+
|
171
|
+
async def delete_bulk(self, id_list: list[str]) -> list[DBModel]:
|
172
|
+
async with self._session_scope() as session:
|
173
|
+
statement = select(self.db_model).where(self.db_model.id.in_(id_list))
|
174
|
+
result = await self._execute_statement(session, statement)
|
175
|
+
entities = result.scalars().all()
|
176
|
+
await self._execute_statement(
|
177
|
+
session, delete(self.db_model).where(self.db_model.id.in_(id_list))
|
178
|
+
)
|
179
|
+
return [self.db_model(**entity.model_dump()) for entity in entities]
|
180
|
+
|
181
|
+
async def update(self, id: str, data: UpdateModel) -> DBModel:
|
182
|
+
now = datetime.datetime.now(datetime.timezone.utc)
|
183
|
+
update_data = self._model_to_data_dict(data, updated_at=now)
|
184
|
+
async with self._session_scope() as session:
|
185
|
+
statement = (
|
186
|
+
update(self.db_model)
|
187
|
+
.where(self.db_model.id == id)
|
188
|
+
.values(**update_data)
|
189
|
+
)
|
190
|
+
await self._execute_statement(session, statement)
|
191
|
+
result = await self._execute_statement(
|
192
|
+
session, select(self.db_model).where(self.db_model.id == id)
|
193
|
+
)
|
194
|
+
updated_instance = result.scalar_one_or_none()
|
195
|
+
if not updated_instance:
|
196
|
+
raise NotFoundError(f"{self.entity_name} not found")
|
197
|
+
return self.db_model(**updated_instance.model_dump())
|
198
|
+
|
199
|
+
async def update_bulk(self, id_list: list[str], data: UpdateModel) -> list[DBModel]:
|
200
|
+
now = datetime.datetime.now(datetime.timezone.utc)
|
201
|
+
update_data = self._model_to_data_dict(data, updated_at=now)
|
202
|
+
update_data = {k: v for k, v in update_data.items() if v is not None}
|
203
|
+
if not update_data:
|
204
|
+
raise InvalidValueError("No valid update data provided")
|
205
|
+
async with self._session_scope() as session:
|
206
|
+
statement = (
|
207
|
+
update(self.db_model)
|
208
|
+
.where(self.db_model.id.in_(id_list))
|
209
|
+
.values(**update_data)
|
210
|
+
)
|
211
|
+
await self._execute_statement(session, statement)
|
212
|
+
result = await self._execute_statement(
|
213
|
+
session, select(self.db_model).where(self.db_model.id.in_(id_list))
|
214
|
+
)
|
215
|
+
return [
|
216
|
+
self.db_model(**entity.model_dump())
|
217
|
+
for entity in result.scalars().all()
|
218
|
+
]
|