fastapi-rtk 2.20.0__tar.gz → 2.21.0__tar.gz
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.
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/PKG-INFO +14 -4
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/README.md +13 -3
- fastapi_rtk-2.21.0/fastapi_rtk/_version.py +1 -0
- fastapi_rtk-2.21.0/fastapi_rtk/agent_docs/adapters/claude/skill.frontmatter +2 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/agent_docs/guide/backend.md +21 -20
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/agent_docs/guide/frontend.md +22 -12
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/agent_docs/guide/jsonforms.md +1 -1
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/cli/test_cli.py +13 -0
- fastapi_rtk-2.20.0/fastapi_rtk/_version.py +0 -1
- fastapi_rtk-2.20.0/fastapi_rtk/agent_docs/adapters/claude/skill.frontmatter +0 -2
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/.gitignore +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/LICENSE +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/agent_docs/adapters/agents-md/AGENTS.md +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/agent_docs/guide/legacy.md +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/agent_docs/guide/overview.md +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/base_api.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/model_rest_api.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/params.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_add_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_bulk_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_delete_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_download_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_edit_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_file_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_info_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_list_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_lookup_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_schema_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_show_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/apis/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/apis/info.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/apis/license.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/auth/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/auth/auth.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/auth/hashers/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/auth/hashers/pbkdf2.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/auth/hashers/scrypt.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/auth/ldap.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/auth/password_helpers/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/auth/password_helpers/fab.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/auth/strategies/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/auth/strategies/config.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/auth/strategies/db.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/auth/strategies/jwt.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/generic/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/generic/column.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/generic/db.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/generic/exceptions.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/generic/filters.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/generic/interface.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/generic/model.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/generic/session.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/column.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/db.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/exceptions.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/extensions/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/extensions/audit/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/extensions/audit/_decorators_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/extensions/audit/_lifecycle_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/extensions/audit/_logger.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/extensions/audit/_processing_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/extensions/audit/audit.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/extensions/audit/types.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/filters.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/extensions/geoalchemy2/geometry_converter.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/filters.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/interface.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/model.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/session.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/bases/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/bases/cache.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/bases/db.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/bases/file_manager.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/bases/filter.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/bases/interface.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/bases/loop_manager.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/bases/model.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/bases/session.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/bases/user_cache.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/caches/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/caches/cache.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/caches/serializers.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/caches/storages.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/cli.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/_security_crypto.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/agent/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/agent/adapters/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/agent/adapters/agents_md.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/agent/adapters/claude.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/agent/base.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/agent/docs.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/db/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/db/templates/fastapi/README +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/db/templates/fastapi/alembic.ini.mako +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/db/templates/fastapi/env.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/db/templates/fastapi/script.py.mako +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/README +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/alembic.ini.mako +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/env.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/db/templates/fastapi-multidb/script.py.mako +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/export.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/security.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/commands/translate.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/const.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/decorators.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/types.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/cli/utils.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/config.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/const.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/db.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/decorators.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/dependencies.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/exceptions.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/fastapi_react_toolkit.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/file_managers/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/file_managers/file_manager.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/file_managers/image_manager.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/file_managers/s3_file_manager.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/file_managers/s3_image_manager.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/filters.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/globals.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/lang/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/lang/babel/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/lang/babel/cli.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/lang/babel/config.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/lang/babel.cfg +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/lang/lazy_text.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/lang/messages.pot +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.mo +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/lang/translations/de/LC_MESSAGES/messages.po +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.mo +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/lang/translations/en/LC_MESSAGES/messages.po +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/loop_managers/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/loop_managers/loop_manager.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/manager.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/middlewares.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/mixins.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/models.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/py.typed +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/registry.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/routers.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/schemas.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/security/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/security/sqla/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/security/sqla/apis.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/security/sqla/models.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/security/sqla/security_manager/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/security/sqla/security_manager/_builtin_role_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/security/sqla/security_manager/_entities.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/security/sqla/security_manager/_exception_filters.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/security/sqla/security_manager/_export.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/security/sqla/security_manager/_import.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/security/sqla/security_manager/_permission_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/security/sqla/security_manager/_results.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/security/sqla/security_manager/_role_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/security/sqla/security_manager/_user_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/security/sqla/security_manager/security_manager.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/security/sqla/user_cache.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/setting.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/types.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/async_task_runner.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/class_factory.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/csv_json_converter.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/deep_merge.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/extender_mixin.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/flask_appbuilder_utils.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/formatter.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/hooks.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/lazy.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/merge_schema.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/multiple_async_contexts.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/pydantic.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/run_utils.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/self_dependencies.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/smartdefaultdict.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/sqla.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/timezone.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/update_signature.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/utils/use_default_when_none.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/version.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/pyproject.toml +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/conftest.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/docker-compose.gis.yml +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/api/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/api/test_add_edit_relation_response.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/api/test_lookup.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/api/test_model_rest_api.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/apis/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/apis/test_info_callable_schema.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/apis/test_info_contract.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/auth/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/auth/test_auth_flow.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/auth/test_oauth.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/conftest.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/file_managers/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/file_managers/test_file_routes.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/security/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/security/sqla/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/security/sqla/conftest.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/security/sqla/test_permission_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/security/sqla/test_role_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/security/sqla/test_security_manager.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/security/sqla/test_user_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/integration/test_app_smoke.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/api/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/api/conftest.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/api/model_rest_api/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/api/model_rest_api/test_columns.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/api/model_rest_api/test_download_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/api/model_rest_api/test_file_mixin.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/api/model_rest_api/test_init.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/api/model_rest_api/test_lookup_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/api/model_rest_api/test_service_delegators.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/api/test_base_api.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/apis/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/apis/test_info.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/apis/test_license.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/auth/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/auth/hashers/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/auth/hashers/test_pbkdf2.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/auth/hashers/test_scrypt.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/auth/password_helpers/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/auth/password_helpers/test_fab.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/auth/strategies/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/auth/strategies/test_config.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/auth/strategies/test_db.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/auth/strategies/test_jwt.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/auth/test_auth.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/generic/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/generic/test_column.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/generic/test_db.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/generic/test_exceptions.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/generic/test_filters.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/generic/test_interface.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/generic/test_model.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/generic/test_session.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/sqla/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/sqla/conftest.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/sqla/test_audit.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/sqla/test_audit_service_delegators.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/sqla/test_audit_types.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/sqla/test_column.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/sqla/test_db.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/sqla/test_filters.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/sqla/test_geoalchemy2.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/sqla/test_interface.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/sqla/test_model.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/backends/sqla/test_session.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/bases/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/bases/test_db.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/bases/test_file_manager.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/bases/test_filter.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/bases/test_interface.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/bases/test_model.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/bases/test_session.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/cli/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/cli/commands/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/cli/commands/conftest.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/cli/commands/test_db.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/cli/commands/test_export.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/cli/commands/test_security.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/cli/commands/test_security_crypto.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/cli/commands/test_translate.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/cli/conftest.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/cli/test_decorators.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/cli/test_types.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/cli/test_utils.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/file_managers/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/file_managers/conftest.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/file_managers/test_file_manager.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/file_managers/test_image_manager.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/file_managers/test_s3_file_manager.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/file_managers/test_s3_image_manager.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/lang/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/lang/test_babel_cli.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/lang/test_babel_config.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/lang/test_lazy_text.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/security/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/security/sqla/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/security/sqla/conftest.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/security/sqla/security_manager/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/security/sqla/security_manager/test_builtin_role_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/security/sqla/security_manager/test_entities.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/security/sqla/security_manager/test_permission_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/security/sqla/security_manager/test_results.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/security/sqla/security_manager/test_role_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/security/sqla/security_manager/test_user_service.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/security/sqla/test_apis.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/security/sqla/test_models.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/security/sqla/test_security_manager.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_caches.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_config.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_const.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_db.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_decorators.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_dependencies.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_exceptions.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_fastapi_react_toolkit.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_filters.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_globals.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_manager.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_middlewares.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_mixins.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_models.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_registry.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_routers.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_schemas.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_setting.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_types.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_user_cache.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/test_version.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/__init__.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_async_task_runner.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_class_factory.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_csv_json_converter.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_deep_merge.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_extender_mixin.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_flask_appbuilder_utils.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_formatter.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_hooks.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_lazy.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_merge_schema.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_multiple_async_contexts.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_pydantic.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_run_utils.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_self_dependencies.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_smartdefaultdict.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_sqla.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_timezone.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_update_signature.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/tests/unit/utils/test_use_default_when_none.py +0 -0
- {fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: fastapi-rtk
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.21.0
|
|
4
4
|
Summary: A package that provides a set of tools to build a FastAPI application with a Class-Based CRUD API.
|
|
5
5
|
Project-URL: Homepage, https://codeberg.org/datatactics/fastapi-rtk
|
|
6
6
|
Project-URL: Issues, https://codeberg.org/datatactics/fastapi-rtk/issues
|
|
@@ -119,7 +119,7 @@ project/
|
|
|
119
119
|
1. Install FastAPI React Toolkit:
|
|
120
120
|
|
|
121
121
|
```bash
|
|
122
|
-
pip install fastapi-rtk
|
|
122
|
+
pip install fastapi-rtk aiosqlite # aiosqlite: async driver for the sqlite URI below (asyncpg for Postgres)
|
|
123
123
|
mkdir -p app
|
|
124
124
|
touch run.py app/__init__.py app/app.py app/config.py app/models.py app/apis.py
|
|
125
125
|
```
|
|
@@ -231,6 +231,7 @@ project/
|
|
|
231
231
|
- `GET /api/v1/items/_image/{filename}` - Serve image files (If image column is present)
|
|
232
232
|
- `GET /api/v1/items/_file/{filename}` - Serve file downloads (If file column is present)
|
|
233
233
|
- `GET /api/v1/items/_info` - Get metadata about the model, including which columns can be added, edited, filtered, etc.
|
|
234
|
+
- `GET /api/v1/items/_lookup/{column}` - Search a column's values, or resolve ids to labels, for form and filter inputs (If the column is enabled in `lookup_columns`)
|
|
234
235
|
- `POST /api/v1/items/bulk/{handler}` - Bulk operations, if set on the API class
|
|
235
236
|
- `GET /api/v1/items/download` - Download items as CSV
|
|
236
237
|
- `GET /api/v1/items/` - List items
|
|
@@ -249,6 +250,14 @@ project/
|
|
|
249
250
|
|
|
250
251
|
2. Project files:
|
|
251
252
|
|
|
253
|
+
**webapp/.env**
|
|
254
|
+
|
|
255
|
+
The path the app is served under, with a trailing slash; `index.html` reads it as `%VITE_BASE_PATH%`.
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
VITE_BASE_PATH=/
|
|
259
|
+
```
|
|
260
|
+
|
|
252
261
|
**webapp/index.html**
|
|
253
262
|
|
|
254
263
|
```html
|
|
@@ -295,7 +304,7 @@ project/
|
|
|
295
304
|
|
|
296
305
|
createRoot(document.getElementById("root")).render(
|
|
297
306
|
<StrictMode>
|
|
298
|
-
<MantineProvider>
|
|
307
|
+
<MantineProvider getStyleNonce={() => window.nonce}>
|
|
299
308
|
<Provider baseUrl={BASE_PATH + "api/v1"}>
|
|
300
309
|
<BrowserRouter basename={BASE_PATH}>
|
|
301
310
|
<App />
|
|
@@ -326,8 +335,9 @@ import { createReactNativeAdapters } from "fastapi-rtk/react-native-adapters";
|
|
|
326
335
|
const rnAdapters = createReactNativeAdapters({
|
|
327
336
|
asyncStorage,
|
|
328
337
|
fileSystem,
|
|
329
|
-
sharing,
|
|
338
|
+
sharing, // optional
|
|
330
339
|
webBrowser,
|
|
340
|
+
oauthRedirectUrl: "myapp://oauth", // required for OAuth sign-in; one URL or a map per provider
|
|
331
341
|
});
|
|
332
342
|
|
|
333
343
|
<Provider baseUrl="https://api.example.com/api/v1" adapters={rnAdapters}>
|
|
@@ -60,7 +60,7 @@ project/
|
|
|
60
60
|
1. Install FastAPI React Toolkit:
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
|
-
pip install fastapi-rtk
|
|
63
|
+
pip install fastapi-rtk aiosqlite # aiosqlite: async driver for the sqlite URI below (asyncpg for Postgres)
|
|
64
64
|
mkdir -p app
|
|
65
65
|
touch run.py app/__init__.py app/app.py app/config.py app/models.py app/apis.py
|
|
66
66
|
```
|
|
@@ -172,6 +172,7 @@ project/
|
|
|
172
172
|
- `GET /api/v1/items/_image/{filename}` - Serve image files (If image column is present)
|
|
173
173
|
- `GET /api/v1/items/_file/{filename}` - Serve file downloads (If file column is present)
|
|
174
174
|
- `GET /api/v1/items/_info` - Get metadata about the model, including which columns can be added, edited, filtered, etc.
|
|
175
|
+
- `GET /api/v1/items/_lookup/{column}` - Search a column's values, or resolve ids to labels, for form and filter inputs (If the column is enabled in `lookup_columns`)
|
|
175
176
|
- `POST /api/v1/items/bulk/{handler}` - Bulk operations, if set on the API class
|
|
176
177
|
- `GET /api/v1/items/download` - Download items as CSV
|
|
177
178
|
- `GET /api/v1/items/` - List items
|
|
@@ -190,6 +191,14 @@ project/
|
|
|
190
191
|
|
|
191
192
|
2. Project files:
|
|
192
193
|
|
|
194
|
+
**webapp/.env**
|
|
195
|
+
|
|
196
|
+
The path the app is served under, with a trailing slash; `index.html` reads it as `%VITE_BASE_PATH%`.
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
VITE_BASE_PATH=/
|
|
200
|
+
```
|
|
201
|
+
|
|
193
202
|
**webapp/index.html**
|
|
194
203
|
|
|
195
204
|
```html
|
|
@@ -236,7 +245,7 @@ project/
|
|
|
236
245
|
|
|
237
246
|
createRoot(document.getElementById("root")).render(
|
|
238
247
|
<StrictMode>
|
|
239
|
-
<MantineProvider>
|
|
248
|
+
<MantineProvider getStyleNonce={() => window.nonce}>
|
|
240
249
|
<Provider baseUrl={BASE_PATH + "api/v1"}>
|
|
241
250
|
<BrowserRouter basename={BASE_PATH}>
|
|
242
251
|
<App />
|
|
@@ -267,8 +276,9 @@ import { createReactNativeAdapters } from "fastapi-rtk/react-native-adapters";
|
|
|
267
276
|
const rnAdapters = createReactNativeAdapters({
|
|
268
277
|
asyncStorage,
|
|
269
278
|
fileSystem,
|
|
270
|
-
sharing,
|
|
279
|
+
sharing, // optional
|
|
271
280
|
webBrowser,
|
|
281
|
+
oauthRedirectUrl: "myapp://oauth", // required for OAuth sign-in; one URL or a map per provider
|
|
272
282
|
});
|
|
273
283
|
|
|
274
284
|
<Provider baseUrl="https://api.example.com/api/v1" adapters={rnAdapters}>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.21.0"
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
name: rtk-developer
|
|
2
|
+
description: 'Use when building, modifying or debugging anything in a fastapi-rtk project: Python models, ModelRestApi or BaseApi endpoints, pre/post hooks, permissions, migrations, file uploads, bulk operations, or the React side (Provider setup, ApiProvider, useApi, NextGenDataGrid, useForms, dialogs, JsonForms). Also on any mention of fastapi-rtk or "rtk backend" / "rtk frontend", and in any project importing from `fastapi_rtk` or the `fastapi-rtk` JS package, where it is preferred over plain FastAPI or React guidance.'
|
|
@@ -39,7 +39,7 @@ FILE_ALLOWED_EXTENSIONS = ["pdf", "csv", "docx", "xlsx"] # optional
|
|
|
39
39
|
IMG_ALLOWED_EXTENSIONS = ["jpg", "jpeg", "png", "gif"] # optional
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
Prefer an **async** driver (`aiosqlite`, `asyncpg`): the toolkit is async-first and the async path is the tested one. A sync URL falls back to a sync engine and session, and `SQLAInterface` runs the sync session calls through `smart_run`.
|
|
43
43
|
|
|
44
44
|
## 3. App initialization (`app/app.py`)
|
|
45
45
|
|
|
@@ -142,18 +142,18 @@ class Item(Model):
|
|
|
142
142
|
|
|
143
143
|
## 5. REST APIs: `ModelRestApi`
|
|
144
144
|
|
|
145
|
-
Registers a full CRUD surface:
|
|
145
|
+
Registers a full CRUD surface under `/api/{version}/{resource_name}` (`version` defaults to `v1`):
|
|
146
146
|
|
|
147
|
-
- `GET /items`: list (supports pagination, filters, sort via query params)
|
|
148
|
-
- `POST /items`: create
|
|
149
|
-
- `GET /items/{id}`: detail
|
|
150
|
-
- `PUT /items/{id}`: update
|
|
151
|
-
- `DELETE /items/{id}`: delete
|
|
152
|
-
- `GET /items/_info`: metadata (columns, filters, permissions), which the frontend uses
|
|
153
|
-
- `GET /items/_lookup/{column}?mode=add|edit|search`: paged values of one column (see "Column lookup" in §8)
|
|
154
|
-
- `GET /items/download`: CSV export
|
|
155
|
-
- `POST /items/bulk/{handler}`: bulk operations (see §12)
|
|
156
|
-
- `GET /items/_file/{filename}` / `_image/{filename}`: served when the model has file/image columns
|
|
147
|
+
- `GET /api/v1/items`: list (supports pagination, filters, sort via query params)
|
|
148
|
+
- `POST /api/v1/items`: create
|
|
149
|
+
- `GET /api/v1/items/{id}`: detail
|
|
150
|
+
- `PUT /api/v1/items/{id}`: update
|
|
151
|
+
- `DELETE /api/v1/items/{id}`: delete
|
|
152
|
+
- `GET /api/v1/items/_info`: metadata (columns, filters, permissions), which the frontend uses
|
|
153
|
+
- `GET /api/v1/items/_lookup/{column}?mode=add|edit|search`: paged values of one column (see "Column lookup" in §8)
|
|
154
|
+
- `GET /api/v1/items/download`: CSV export
|
|
155
|
+
- `POST /api/v1/items/bulk/{handler}`: bulk operations (see §12)
|
|
156
|
+
- `GET /api/v1/items/_file/{filename}` / `_image/{filename}`: served when the model has file/image columns
|
|
157
157
|
|
|
158
158
|
```python
|
|
159
159
|
from fastapi_rtk import ModelRestApi, SQLAInterface, g
|
|
@@ -260,7 +260,7 @@ By default every column is listed, shown, added, edited. Override per-operation:
|
|
|
260
260
|
class ItemApi(ModelRestApi):
|
|
261
261
|
datamodel = SQLAInterface(Item)
|
|
262
262
|
|
|
263
|
-
list_columns = ["id", "name", "category.name"] # GET /items
|
|
263
|
+
list_columns = ["id", "name", "category.name"] # GET /api/v1/items
|
|
264
264
|
show_columns = ["id", "name", "description", "category"]
|
|
265
265
|
add_columns = ["name", "description", "category"]
|
|
266
266
|
edit_columns = ["name", "description"] # can't reassign category
|
|
@@ -297,7 +297,7 @@ More per-Api knobs:
|
|
|
297
297
|
|
|
298
298
|
### Column lookup
|
|
299
299
|
|
|
300
|
-
`/_info` ships only the first `max_page_size` options of a relation; `GET /items/_lookup/{column}` searches and pages the values of one column instead. Query params, bound as one `LookupQuerySchema` (per-Api `lookup_query_schema`): `mode` (required: `add`, `edit` or `search`; any other value is 422), `search` (text the values must contain, matched by `FilterSearch` like the list route's `search` param), `page` (zero-based, default 0), `page_size` (default and cap `max_page_size`), `ids` (a JSON list of primary keys to resolve, default `[]`). The response is `LookupResponse`, `{"count": int, "values": [...]}`: `{"id", "value"}` entries for a relation (`value` is `str(item)`), distinct non-null scalars in ascending order for a plain column. The route is dropped from `routes` when no column is lookup-enabled in any mode.
|
|
300
|
+
`/_info` ships only the first `max_page_size` options of a relation; `GET /api/v1/items/_lookup/{column}` searches and pages the values of one column instead. Query params, bound as one `LookupQuerySchema` (per-Api `lookup_query_schema`): `mode` (required: `add`, `edit` or `search`; any other value is 422), `search` (text the values must contain, matched by `FilterSearch` like the list route's `search` param), `page` (zero-based, default 0), `page_size` (default and cap `max_page_size`), `ids` (a JSON list of primary keys to resolve, default `[]`). The response is `LookupResponse`, `{"count": int, "values": [...]}`: `{"id", "value"}` entries for a relation (`value` is `str(item)`), distinct non-null scalars in ascending order for a plain column. The route is dropped from `routes` when no column is lookup-enabled in any mode.
|
|
301
301
|
|
|
302
302
|
- Query validation (400, before access): `ids` that is not JSON (`json_invalid`) or not a list (`list_type`), a negative `page` (`greater_than_equal`), a `page_size` below 1 (`greater_than`).
|
|
303
303
|
- Gating order: 401 (route protected, no user), 404 `COLUMN_NOT_FOUND` (column not lookup-enabled in that mode), 403 (user lacks `can_post` for `add`, `can_put` for `edit`, `can_get` for `search`). There is no `can_lookup` permission; `"lookup"` in `exclude_protected_routes` skips the 401 and 403 checks.
|
|
@@ -414,7 +414,7 @@ class Item(Model):
|
|
|
414
414
|
When these columns exist, `ModelRestApi` automatically:
|
|
415
415
|
|
|
416
416
|
- switches POST/PUT to `multipart/form-data`
|
|
417
|
-
- exposes `GET /items/_file/{filename}` and `GET /items/_image/{filename}`
|
|
417
|
+
- exposes `GET /api/v1/items/_file/{filename}` and `GET /api/v1/items/_image/{filename}`
|
|
418
418
|
- grants `can_file` / `can_image` permissions
|
|
419
419
|
|
|
420
420
|
### File managers
|
|
@@ -574,12 +574,13 @@ class ReadingApi(ModelRestApi):
|
|
|
574
574
|
download_page_size = 5000
|
|
575
575
|
```
|
|
576
576
|
|
|
577
|
-
Set it to a resolver when the size depends on the query. It receives the Api, the session, and the `DBQueryParams` the export runs with. Sync and async both work, resolved through `safe_call`, so a sync one runs inline rather than on a worker thread
|
|
577
|
+
Set it to a resolver when the size depends on the query. It receives the Api, the session, and the `DBQueryParams` the export runs with. Sync and async both work, resolved through `safe_call`, so a sync one runs inline rather than on a worker thread. Declare it in the class body as a `@staticmethod`: a plain method is called with `self` prepended and raises `TypeError`.
|
|
578
578
|
|
|
579
579
|
```python
|
|
580
580
|
class ReadingApi(ModelRestApi):
|
|
581
581
|
datamodel = SQLAInterface(Reading)
|
|
582
582
|
|
|
583
|
+
@staticmethod
|
|
583
584
|
def download_page_size(api, session, params):
|
|
584
585
|
return 1000 if params.get("filters") else 250
|
|
585
586
|
```
|
|
@@ -619,9 +620,9 @@ Top-level shape: `dict[role_name, list[[api_glob, permission_glob]]]`. Both fiel
|
|
|
619
620
|
|
|
620
621
|
### The admin role sits outside `ROLES`
|
|
621
622
|
|
|
622
|
-
`Setting.AUTH_ROLE_ADMIN` (`setting.py:368`, default `DEFAULT_ADMIN_ROLE = "Admin"` from `const.py:
|
|
623
|
+
`Setting.AUTH_ROLE_ADMIN` (`setting.py:368`, default `DEFAULT_ADMIN_ROLE = "Admin"` from `const.py:74`) names a role that is deliberately absent from `ROLES`, reachable as `g.admin_role` (`globals.py:142-149`). It holds **every permission of every registered Api**, and a `ROLES` edit cannot narrow that: `_associate_permission_with_api` (`fastapi_react_toolkit.py:506`) writes one `PermissionApi` row per `(permission, api)` taken from each Api's exposed routes plus one per `ROLES` entry, then `_associate_role_with_permission_api` (`:545`) grants the admin role every one of those rows except the ones whose permission name contains `|` and that a `ROLES` role other than the public role lists (`:562-577`; a piped entry listed only under the public role is still granted to admin). The per-route row for the same permission is a different row and is never excluded, so piping a `ROLES` entry to hide something from the admin role is a no-op. The cleanup pass also exempts that role from disassociation by name, so an existing grant row survives every restart.
|
|
623
624
|
|
|
624
|
-
Revoking a permission from it means setting `AUTH_ROLE_ADMIN` to `None`
|
|
625
|
+
Revoking a permission from it means setting `AUTH_ROLE_ADMIN` to `None` (which strips the blanket grant entirely, since `if g.admin_role:` guards it), or checking inside the route. Pointing `AUTH_ROLE_ADMIN` at an existing `ROLES` role name revokes nothing: that role becomes the admin role, receives the blanket grant, and is exempt from cleanup.
|
|
625
626
|
|
|
626
627
|
### Asking whether a user holds a permission
|
|
627
628
|
|
|
@@ -661,7 +662,7 @@ A name listed in an Api's `base_permissions` that no exposed route carries becom
|
|
|
661
662
|
|
|
662
663
|
### What the browser gets
|
|
663
664
|
|
|
664
|
-
`GET auth/user` sets `permissions` to the **Api names** the user holds any grant on, not permission names: `select(Api.name).join(PermissionApi).join(PermissionApi.roles).where(Role.id.in_(user role ids)).distinct()` (`security/sqla/apis.py:
|
|
665
|
+
`GET auth/user` sets `permissions` to the **Api names** the user holds any grant on, not permission names: `select(Api.name).join(PermissionApi).join(PermissionApi.roles).where(Role.id.in_(user role ids)).distinct()` (`security/sqla/apis.py:155-166`), typed as `AuthUser.permissions: string[]` in the JS client. So a browser-side gate can ask "any grant on Api A" and cannot distinguish `can_get` from `can_post`; per-permission detail reaches the frontend through an Api's `_info` response instead (`InfoResponse.permissions`, `schemas.py:302`). Prefer that Api-level fact over publishing a role list in the frontend config, and keep the enforcing check server-side.
|
|
665
666
|
|
|
666
667
|
### Route guards
|
|
667
668
|
|
|
@@ -717,7 +718,7 @@ A `"backend": "jwt"` client (for clients without a browser cookie store, such as
|
|
|
717
718
|
|
|
718
719
|
```bash
|
|
719
720
|
fastapi-rtk db init
|
|
720
|
-
fastapi-rtk db migrate
|
|
721
|
+
fastapi-rtk db migrate --message "add items"
|
|
721
722
|
fastapi-rtk db upgrade
|
|
722
723
|
fastapi-rtk db downgrade
|
|
723
724
|
|
|
@@ -10,7 +10,7 @@ The toolkit expects Mantine as the UI kit. Use `Stack`, `Group`, `Grid`, `Simple
|
|
|
10
10
|
pnpm add fastapi-rtk @mantine/core @mantine/dates @mantine/form @mantine/hooks dayjs react-router
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
Peer deps: the four `@mantine/*` packages (`^9.
|
|
13
|
+
Peer deps: the four `@mantine/*` packages (`^9.4.0`), `react` / `react-dom` (`^19.2.3`), `dayjs` (`^1.11.0`) and `react-router` (`^7.5.3 || ^8.0.0`), plus the optional `@jsonforms/core` / `@jsonforms/react` (`^3.6.0`), needed only when importing from `fastapi-rtk/jsonforms` (every other subpath, its types included, works without them). TanStack Query (`^5.52.1`), zustand, i18next, react-i18next, yup, lodash, clsx and dompurify are regular dependencies, installed with `fastapi-rtk`; only mantine-react-table (patched), mantine-form-yup-resolver and the JsonForms copy behind the built-in forms are bundled inside it. When the app's own TanStack Query or react-i18next resolves to the same copy, its `useQuery` / `useQueryClient` / `useTranslation` inside a `Provider` read the Provider's `QueryClient` and i18next instance, since `Provider` always creates its own `QueryClient`; `rq` / `i18nr` / `useTranslation` imported from `fastapi-rtk` always do. Outside a `Provider`, the app's `useTranslation` keeps the app's own i18next instance. To keep the app's own instance inside a `Provider` as well, pass it as `langProps.i18n`. Mantine >= 9.4.1 requires fastapi-rtk >= 2.8.0; older releases loop forever in the grid's `useColumns` ("Maximum update depth exceeded").
|
|
14
14
|
|
|
15
15
|
**Provider order is load-bearing.** Mantine must wrap the fastapi-rtk `Provider`, and the stylesheet order matters: Mantine CSS first, fastapi-rtk CSS last (RTK overrides).
|
|
16
16
|
|
|
@@ -105,7 +105,7 @@ function ItemsPage() {
|
|
|
105
105
|
| `data` | Current list/page payload for the bound resource |
|
|
106
106
|
| `info` | The `/_info` response for the resource (`add_columns`, `edit_columns`, `permissions`, …) |
|
|
107
107
|
| `loading` / `dataLoading` / `infoLoading` | Aggregate + per-stream fetch flags |
|
|
108
|
-
| `error` / `dataError` / `infoError` | Aggregate + per-stream
|
|
108
|
+
| `error` / `dataError` / `infoError` | Aggregate `{message, originalError}` object + the per-stream raw query `Error` objects |
|
|
109
109
|
| `getEntry(id)` | `GET /{resource}/{id}` |
|
|
110
110
|
| `addEntry(item)` | `POST /{resource}` |
|
|
111
111
|
| `updateEntry(id, item)` | `PUT /{resource}/{id}` |
|
|
@@ -147,7 +147,7 @@ await addEntry({ name: "x" }); // POST /{resource}
|
|
|
147
147
|
await updateEntry(id, { name: "y" }); // PUT /{resource}/{id}
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
**Option B, use the TanStack Query namespace `rq`.** `fastapi-rtk` re-exports `@tanstack/react-query` as `rq` (`export * as rq from '
|
|
150
|
+
**Option B, use the TanStack Query namespace `rq`.** `fastapi-rtk` re-exports its `@tanstack/react-query` as `rq` (`export * as rq from './rq'` in `externals/src/index.ts`, surfaced by `core/src/index.ts:94`; import it from there rather than from `@tanstack/react-query`, since an app's own copy sees the Provider's `QueryClient` only when it resolves to the same install; the sibling `mrt` namespace re-exports the bundled `mantine-react-table` the same way, with long-form aliases `reactQuery` / `mantineReactTable` at `core/src/index.ts:96`). The same namespaces, plus `ld` (lodash), `zs` (zustand), `yup` and `i18nr` (react-i18next), are importable from `fastapi-rtk` or `fastapi-rtk/externals`; importing them from `fastapi-rtk/api`, `/utils`, `/zustand` or `/contexts` is deprecated. Wrap a `useApi` action (or any toolkit-provided async function) in `rq.useQuery` / `rq.useMutation` so the result participates in the shared query cache (invalidation, refetch-on-focus, devtools). Never call raw `fetch` from the `queryFn` / `mutationFn`, since that re-introduces the exact problems `useCustomFetch` has.
|
|
151
151
|
|
|
152
152
|
```jsx
|
|
153
153
|
import { useApi, rq } from "fastapi-rtk";
|
|
@@ -169,7 +169,7 @@ function ReportsPanel({ id }) {
|
|
|
169
169
|
}
|
|
170
170
|
```
|
|
171
171
|
|
|
172
|
-
**Combine with `useApi` for cross-resource updates.** Use a `useApi` action for the bound resource and `rq.useMutation` wrapping a sibling `useApi` action for the second resource. To refresh the bound resource's grid after a mutation, call `refetch({ force: true })` from `useApi()` inside `onSuccess`, which hits the same query the grid renders from (`['data', path, queryParamsJSON, lang]` in `useProvideApi.
|
|
172
|
+
**Combine with `useApi` for cross-resource updates.** Use a `useApi` action for the bound resource and `rq.useMutation` wrapping a sibling `useApi` action for the second resource. To refresh the bound resource's grid after a mutation, call `refetch({ force: true })` from `useApi()` inside `onSuccess`, which hits the same query the grid renders from (`['data', path, queryParamsJSON, lang]` in `useProvideApi.ts`). Toolkit-internal key shape is an implementation detail; use the `useApi` helpers to invalidate rather than constructing the key yourself.
|
|
173
173
|
|
|
174
174
|
**Last resort: `useCustomFetch`.** Still exported for legacy call sites. Signature: `useCustomFetch(url, { autoInvoke, initialLoading, clearDataOnRefetch, ...fetchOptions })`; returns `{ data, loading, error, refetch, abort, resetError }`. `refetch()` re-runs the request with the URL + options bound at hook creation; there is no `execute(...)` and no per-call body override. If you need either, switch to `rq.useMutation`.
|
|
175
175
|
|
|
@@ -202,12 +202,22 @@ info?.forEach((api) => /* render menu entry for api.path */);
|
|
|
202
202
|
```jsx
|
|
203
203
|
import { useAuth } from "fastapi-rtk";
|
|
204
204
|
|
|
205
|
-
const {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
205
|
+
const {
|
|
206
|
+
user,
|
|
207
|
+
error,
|
|
208
|
+
signin,
|
|
209
|
+
signout,
|
|
210
|
+
oauthSignin,
|
|
211
|
+
oauthCallback,
|
|
212
|
+
update,
|
|
213
|
+
resetPassword,
|
|
214
|
+
refetch,
|
|
215
|
+
} = useAuth();
|
|
216
|
+
|
|
217
|
+
await signin({ username, password }); // a single credentials object
|
|
218
|
+
await oauthSignin("google", /* popup */ false); // oauth_signin is the deprecated alias
|
|
210
219
|
await signout();
|
|
220
|
+
error?.message; // { message, originalError } of the last failed action, or undefined
|
|
211
221
|
|
|
212
222
|
user?.username;
|
|
213
223
|
user?.roles; // string[] of role names
|
|
@@ -216,7 +226,7 @@ user?.permissions; // string[] of API NAMES the user holds any grant on
|
|
|
216
226
|
|
|
217
227
|
Gate routes/components on `user` and `user.roles`. The Provider keeps the session via cookie, so `user` is populated on every page load automatically.
|
|
218
228
|
|
|
219
|
-
An OAuth provider configured with `"backend": "jwt"` is for clients without a browser cookie store (React Native on `createReactNativeAdapters`, whose bearer transport stores the token); web apps default to `cookie` providers, since a bearer transport on web keeps the token in `localStorage`, readable by any script on the origin. A web app can still opt into JWT: `adapters={{ authTransport: createBearerTransport(webAdapters.storage) }}`, the provider's `redirect_url` at an app route, and `oauthCallback("google", window.location.search)` on that route. On React Native: point the provider's `redirect_url` at the app's deep link (`myapp://oauth/google`), pass the same URL as `createReactNativeAdapters({ ..., oauthRedirectUrl })` (a string for every provider, or `{ google: "myapp://oauth/google", github: "..." }` keyed by provider name), and call `oauthSignin("google", false)` (no popup). A provider missing from that map fails before any browser opens (`error` is `Could not sign in`, `originalError` names the provider). iOS ends the session on any URL with the redirect URL's scheme (so `myapp://oauth/google` and `myapp://oauth/github` are not told apart there), Android on the first deep link starting with it; for an `https` redirect on iOS 17.4+ pass `oauthPreferUniversalLinks: true` (needs the Associated Domains entitlement) to match host and path instead. The RN opener runs `webBrowser.openAuthSessionAsync(loginUrl, oauthRedirectUrl, { preferUniversalLinks })` and hands the redirected URL back, and `oauthSignin` forwards its `code` / `state` to `auth/oauth-authorized/<provider>`, stores the returned token through `authTransport.persistLogin`, and refetches the user; a failure sets `error` to `Could not sign in`. An app that receives the redirect another way calls `oauthCallback("google", redirectQuery)` from `useAuth()` with that URL's query string.
|
|
229
|
+
An OAuth provider configured with `"backend": "jwt"` is for clients without a browser cookie store (React Native on `createReactNativeAdapters`, whose bearer transport stores the token); web apps default to `cookie` providers, since a bearer transport on web keeps the token in `localStorage`, readable by any script on the origin. A web app can still opt into JWT: `adapters={{ authTransport: createBearerTransport(webAdapters.storage) }}`, the provider's `redirect_url` at an app route, and `oauthCallback("google", window.location.search)` on that route. On React Native: point the provider's `redirect_url` at the app's deep link (`myapp://oauth/google`), pass the same URL as `createReactNativeAdapters({ ..., oauthRedirectUrl })` (a string for every provider, or `{ google: "myapp://oauth/google", github: "..." }` keyed by provider name), and call `oauthSignin("google", false)` (no popup). A provider missing from that map fails before any browser opens (`error.message` is `Could not sign in`, `error.originalError` names the provider). iOS ends the session on any URL with the redirect URL's scheme (so `myapp://oauth/google` and `myapp://oauth/github` are not told apart there), Android on the first deep link starting with it; for an `https` redirect on iOS 17.4+ pass `oauthPreferUniversalLinks: true` (needs the Associated Domains entitlement) to match host and path instead. The RN opener runs `webBrowser.openAuthSessionAsync(loginUrl, oauthRedirectUrl, { preferUniversalLinks })` and hands the redirected URL back, and `oauthSignin` forwards its `code` / `state` to `auth/oauth-authorized/<provider>`, stores the returned token through `authTransport.persistLogin`, and refetches the user; a failure sets `error.message` to `Could not sign in`. An app that receives the redirect another way calls `oauthCallback("google", redirectQuery)` from `useAuth()` with that URL's query string.
|
|
220
230
|
|
|
221
231
|
**`user.permissions` holds Api names, not permission names.** `auth/user` builds it as `select(Api.name)` joined through the user's roles (backend reference §14, "What the browser gets"), so `user.permissions.includes("ItemApi")` answers "has any grant on that Api" and nothing finer: `can_get` and `can_post` are indistinguishable there. It is the right gate for "may this user reach this resource at all", and it beats shipping a role list through the frontend config, since it follows the grants themselves and leaves no second list to keep in step. For per-verb detail read `useApi().info.permissions` (§5), which is that Api's `/_info` intersected with the user's grants.
|
|
222
232
|
|
|
@@ -403,7 +413,7 @@ const { t } = useTranslation(); // or: translation.t
|
|
|
403
413
|
<LanguageSelector />;
|
|
404
414
|
```
|
|
405
415
|
|
|
406
|
-
`useLang` reads/writes the selected language to localStorage. The translation function `t(key)` comes from
|
|
416
|
+
`useLang` reads/writes the selected language to localStorage. The translation function `t(key)` comes from the `useTranslation()` exported by `fastapi-rtk` (the react-i18next one, which the Provider wires to its i18next instance, as it does `i18nr.Trans`; the one imported from `react-i18next` itself sees it only when the app's react-i18next resolves to the same install) or via the `translation` field on `useLang()`. Source strings double as the English keys; a German dictionary ships built-in. Extend or override through the `Provider`'s `langProps` prop: `langProps.getI18nProps.translations` takes `{locale: {key: value}}`, `langProps.i18n` accepts a full i18next instance, and `langProps.MRTLocalization` overrides the grid's Mantine React Table strings.
|
|
407
417
|
|
|
408
418
|
## 13. Standard routes: `UserMenu`
|
|
409
419
|
|
|
@@ -473,7 +483,7 @@ Cookie login is on by default on the backend; the JWT endpoint exists only when
|
|
|
473
483
|
|
|
474
484
|
## 15. Other notable exports
|
|
475
485
|
|
|
476
|
-
- Every context hook accepts safe-context options: `useApi({ throwOnError: false })` returns `
|
|
486
|
+
- Every context hook accepts safe-context options: `useApi({ throwOnError: false })` returns the `defaultValue` option (an empty object `{}` unless you pass one) instead of throwing outside its provider (same option on the other hooks).
|
|
477
487
|
- Headless fetcher layer for code outside any provider: `buildRequest`, `getItems` / `getItem` / `createItem` / `updateItem` / `deleteItem` / `getInfo`, `formCreateItem` / `formUpdateItem`, `uploadItems` / `downloadItems`, `postBulk`, plus `useAdapters` / `webAdapters`.
|
|
478
488
|
- Legacy `DataGrid` is still exported alongside `NextGenDataGrid`; standalone `ActionIcons` (`Actions`, `Add`, `Delete`, `Download`, `Edit`, `Refresh`, `Upload`, `View`) and `Filter` compose custom layouts.
|
|
479
489
|
- Utilities: `deepMerge`, `parseFromValuesOrFunc`, `createSafeContext`, `getItemId`, `urlJoin`, `Memoizer`, `FastAPIRTKLogger`; hooks `useActionIcon`, `useSyncValues`, `useTrueOnce`.
|
|
@@ -92,7 +92,7 @@ const customizer = {
|
|
|
92
92
|
- `componentProps` : the fully computed Mantine props the built-in would have used: `value`, `onChange` (already wired to JsonForms `handleChange(path, value)`), `onBlur`, `label`, `description`, `required`, `disabled`, `error`, plus `uischema.options.props` and `ifProps` (§2). Spread it onto a value-based Mantine input and the field is controlled and validated for free.
|
|
93
93
|
- `jsonFormsProps` : the raw control props (`data`, `handleChange`, `path`, `schema`, `uischema`, `enabled`, `errors`, `visible`, `id`). Reach here when `componentProps` is not enough, or call `useCommonProps(jsonFormsProps)` (from `fastapi-rtk`) to have the library rebuild the `handleChange(path, value)` wrapper for you.
|
|
94
94
|
|
|
95
|
-
`key` is a **renderer name** (`Text`, `Number`, `Integer`, `Boolean`, `Date`, `DateTime`, `Time`, `Enum`, `EnumArray`, `OneOfEnum`, `File`, `Image`, `Json`, `Object`, `Label`, `Table`, `Array`, `Array.Accordion`), a **JsonForms path / field name** (`status`, `details.category`), or `all`. Precedence when several match: `all` < renderer-name < path (slots deep-merge in that order, most specific wins). Since 2.8.0 every structural wrapper is addressable too: `Table.Thead` / `Table.Tbody` / `Table.Empty`, `Table.Header.*` (`Tr`, `Actions`, `Validation`, `Toolbar`, `Wrapper`, `Flex`), `Table.Row.*` (`Tr`, `Td`, `Actions`, `Grid`, `Up`, `Down`, `Remove`), per-row / per-cell addressing (`Table.Row.{index}`, `Table.Row.{index}.{subPath}`, `Table.Row.{subPath}`), `Array.Stack` / `Array.Items` / `Array.Empty` / `Array.Header.*` / `Array.Item.*` / `Array.DeleteDialog`, `File.Box` / `Image.Box`, and `Label.{text}`. (Collision escape: when
|
|
95
|
+
`key` is a **renderer name** (`Text`, `Number`, `Integer`, `Boolean`, `Date`, `DateTime`, `Time`, `Enum`, `EnumArray`, `OneOfEnum`, `File`, `Image`, `Json`, `Object`, `Label`, `Table`, `Array`, `Array.Accordion`), a **JsonForms path / field name** (`status`, `details.category`), or `all`. Precedence when several match: `all` < renderer-name < path (slots deep-merge in that order, most specific wins). Since 2.8.0 every structural wrapper is addressable too: `Table.Thead` / `Table.Tbody` / `Table.Empty`, `Table.Header.*` (`Tr`, `Actions`, `Validation`, `Toolbar`, `Wrapper`, `Flex`), `Table.Row.*` (`Tr`, `Td`, `Actions`, `Grid`, `Up`, `Down`, `Remove`), per-row / per-cell addressing (`Table.Row.{index}`, `Table.Row.{index}.{subPath}`, `Table.Row.{subPath}`), `Array.Stack` / `Array.Items` / `Array.Empty` / `Array.Header.*` / `Array.Item.*` / `Array.DeleteDialog`, `File.Box` / `Image.Box`, and `Label.{text}`. (Collision escape: when the resource's `list_columns` contains a column named `all`, the wildcard key becomes `_all`; read it at runtime as `useApi().specialKey.all`, which is `all` outside an `ApiProvider`.)
|
|
96
96
|
|
|
97
97
|
**Write the component** as a plain Mantine component. For a blob field, `JSON.parse` on read and `JSON.stringify` on write; keep spreading `{...componentProps}` so the label / description / error wrapper still renders:
|
|
98
98
|
|
|
@@ -7,6 +7,8 @@ import zipfile
|
|
|
7
7
|
|
|
8
8
|
import typer.main
|
|
9
9
|
import typer.testing
|
|
10
|
+
import yaml
|
|
11
|
+
|
|
10
12
|
from fastapi_rtk.cli.cli import app, main
|
|
11
13
|
from fastapi_rtk.cli.commands.agent.adapters import AgentsMDAdapter, ClaudeAdapter
|
|
12
14
|
from fastapi_rtk.cli.commands.agent.base import AbstractAgentAdapter
|
|
@@ -290,6 +292,17 @@ class TestInstallAgentDocs:
|
|
|
290
292
|
assert skill.startswith("---\nname: rtk-developer\n")
|
|
291
293
|
assert GUIDE_TARGET in skill
|
|
292
294
|
|
|
295
|
+
def test_skill_frontmatter_is_valid_yaml(self, tmp_path):
|
|
296
|
+
runner.invoke(
|
|
297
|
+
app, ["agent", "install", "--directory", str(tmp_path), "--claude"]
|
|
298
|
+
)
|
|
299
|
+
skill = (tmp_path / SKILL_TARGET / "SKILL.md").read_text()
|
|
300
|
+
frontmatter = yaml.safe_load(skill.split("---\n")[1])
|
|
301
|
+
assert frontmatter["name"] == "rtk-developer"
|
|
302
|
+
assert frontmatter["description"].startswith(
|
|
303
|
+
"Use when building, modifying or debugging anything in a fastapi-rtk project: "
|
|
304
|
+
)
|
|
305
|
+
|
|
293
306
|
def test_guide_and_skill_carry_the_same_pointers(self, tmp_path):
|
|
294
307
|
runner.invoke(
|
|
295
308
|
app, ["agent", "install", "--directory", str(tmp_path), "--claude"]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.20.0"
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
name: rtk-developer
|
|
2
|
-
description: Use when building, modifying or debugging anything in a fastapi-rtk project: Python models, ModelRestApi or BaseApi endpoints, pre/post hooks, permissions, migrations, file uploads, bulk operations, or the React side (Provider setup, ApiProvider, useApi, NextGenDataGrid, useForms, dialogs, JsonForms). Also on any mention of fastapi-rtk or "rtk backend" / "rtk frontend", and in any project importing from `fastapi_rtk` or the `fastapi-rtk` JS package, where it is preferred over plain FastAPI or React guidance.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/agent_docs/adapters/agents-md/AGENTS.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/__init__.py
RENAMED
|
File without changes
|
{fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_add_service.py
RENAMED
|
File without changes
|
{fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_bulk_service.py
RENAMED
|
File without changes
|
{fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_delete_service.py
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_edit_service.py
RENAMED
|
File without changes
|
{fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_file_service.py
RENAMED
|
File without changes
|
{fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_info_service.py
RENAMED
|
File without changes
|
{fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_list_service.py
RENAMED
|
File without changes
|
{fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_lookup_service.py
RENAMED
|
File without changes
|
{fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_schema_service.py
RENAMED
|
File without changes
|
{fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/api/model_rest_api/services/_show_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/extensions/audit/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/extensions/audit/_logger.py
RENAMED
|
File without changes
|
|
File without changes
|
{fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/extensions/audit/audit.py
RENAMED
|
File without changes
|
{fastapi_rtk-2.20.0 → fastapi_rtk-2.21.0}/fastapi_rtk/backends/sqla/extensions/audit/types.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|