aso 0.2.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.
- aso-0.2.0/.gitignore +48 -0
- aso-0.2.0/.python-version +1 -0
- aso-0.2.0/BUILD.md +75 -0
- aso-0.2.0/PKG-INFO +100 -0
- aso-0.2.0/README.md +57 -0
- aso-0.2.0/pyproject.toml +108 -0
- aso-0.2.0/skeleton/.env.example +26 -0
- aso-0.2.0/skeleton/.env.testing +20 -0
- aso-0.2.0/skeleton/.gitignore +24 -0
- aso-0.2.0/skeleton/AGENTS.md +49 -0
- aso-0.2.0/skeleton/LICENSES/laravel-react-starter-kit.md +35 -0
- aso-0.2.0/skeleton/app/__init__.py +0 -0
- aso-0.2.0/skeleton/app/actions/__init__.py +0 -0
- aso-0.2.0/skeleton/app/actions/auth/__init__.py +0 -0
- aso-0.2.0/skeleton/app/actions/auth/create_new_user.py +16 -0
- aso-0.2.0/skeleton/app/actions/auth/password_validation_rules.py +28 -0
- aso-0.2.0/skeleton/app/actions/auth/reset_user_password.py +15 -0
- aso-0.2.0/skeleton/app/console/__init__.py +0 -0
- aso-0.2.0/skeleton/app/console/commands/__init__.py +0 -0
- aso-0.2.0/skeleton/app/exceptions/__init__.py +0 -0
- aso-0.2.0/skeleton/app/http/__init__.py +0 -0
- aso-0.2.0/skeleton/app/http/controllers/__init__.py +0 -0
- aso-0.2.0/skeleton/app/http/controllers/auth/__init__.py +0 -0
- aso-0.2.0/skeleton/app/http/controllers/auth/authenticated_session_controller.py +32 -0
- aso-0.2.0/skeleton/app/http/controllers/auth/confirmable_password_controller.py +24 -0
- aso-0.2.0/skeleton/app/http/controllers/auth/email_verification_notification_controller.py +15 -0
- aso-0.2.0/skeleton/app/http/controllers/auth/email_verification_prompt_controller.py +15 -0
- aso-0.2.0/skeleton/app/http/controllers/auth/new_password_controller.py +27 -0
- aso-0.2.0/skeleton/app/http/controllers/auth/password_reset_link_controller.py +20 -0
- aso-0.2.0/skeleton/app/http/controllers/auth/registered_user_controller.py +24 -0
- aso-0.2.0/skeleton/app/http/controllers/auth/verify_email_controller.py +23 -0
- aso-0.2.0/skeleton/app/http/controllers/dashboard_controller.py +9 -0
- aso-0.2.0/skeleton/app/http/controllers/settings/__init__.py +0 -0
- aso-0.2.0/skeleton/app/http/controllers/settings/profile_controller.py +39 -0
- aso-0.2.0/skeleton/app/http/controllers/settings/security_controller.py +20 -0
- aso-0.2.0/skeleton/app/http/middleware/__init__.py +0 -0
- aso-0.2.0/skeleton/app/http/middleware/handle_appearance.py +25 -0
- aso-0.2.0/skeleton/app/http/middleware/handle_inertia_requests.py +17 -0
- aso-0.2.0/skeleton/app/http/requests/__init__.py +0 -0
- aso-0.2.0/skeleton/app/http/requests/auth/__init__.py +0 -0
- aso-0.2.0/skeleton/app/http/requests/auth/confirm_password_request.py +7 -0
- aso-0.2.0/skeleton/app/http/requests/auth/forgot_password_request.py +9 -0
- aso-0.2.0/skeleton/app/http/requests/auth/login_request.py +41 -0
- aso-0.2.0/skeleton/app/http/requests/auth/register_request.py +16 -0
- aso-0.2.0/skeleton/app/http/requests/auth/reset_password_request.py +16 -0
- aso-0.2.0/skeleton/app/http/requests/settings/__init__.py +0 -0
- aso-0.2.0/skeleton/app/http/requests/settings/delete_user_request.py +10 -0
- aso-0.2.0/skeleton/app/http/requests/settings/password_update_request.py +13 -0
- aso-0.2.0/skeleton/app/http/requests/settings/profile_update_request.py +13 -0
- aso-0.2.0/skeleton/app/jobs/__init__.py +0 -0
- aso-0.2.0/skeleton/app/listeners/__init__.py +0 -0
- aso-0.2.0/skeleton/app/listeners/send_email_verification_notification.py +14 -0
- aso-0.2.0/skeleton/app/mail/__init__.py +0 -0
- aso-0.2.0/skeleton/app/models/__init__.py +0 -0
- aso-0.2.0/skeleton/app/models/user.py +19 -0
- aso-0.2.0/skeleton/app/policies/__init__.py +0 -0
- aso-0.2.0/skeleton/bootstrap/app.py +30 -0
- aso-0.2.0/skeleton/components.json +21 -0
- aso-0.2.0/skeleton/config/app.py +12 -0
- aso-0.2.0/skeleton/config/auth.py +50 -0
- aso-0.2.0/skeleton/config/cache.py +14 -0
- aso-0.2.0/skeleton/config/database.py +34 -0
- aso-0.2.0/skeleton/config/filesystems.py +18 -0
- aso-0.2.0/skeleton/config/hashing.py +9 -0
- aso-0.2.0/skeleton/config/inertia.py +10 -0
- aso-0.2.0/skeleton/config/logging.py +18 -0
- aso-0.2.0/skeleton/config/mail.py +28 -0
- aso-0.2.0/skeleton/config/queue.py +14 -0
- aso-0.2.0/skeleton/config/session.py +19 -0
- aso-0.2.0/skeleton/database/__init__.py +0 -0
- aso-0.2.0/skeleton/database/factories/__init__.py +0 -0
- aso-0.2.0/skeleton/database/factories/user_factory.py +22 -0
- aso-0.2.0/skeleton/database/migrations/2026_01_01_000000_create_users_table.py +62 -0
- aso-0.2.0/skeleton/database/migrations/__init__.py +0 -0
- aso-0.2.0/skeleton/database/seeders/__init__.py +0 -0
- aso-0.2.0/skeleton/database/seeders/database_seeder.py +8 -0
- aso-0.2.0/skeleton/package-lock.json +2625 -0
- aso-0.2.0/skeleton/package.json +42 -0
- aso-0.2.0/skeleton/public/.gitkeep +0 -0
- aso-0.2.0/skeleton/public/favicon.svg +12 -0
- aso-0.2.0/skeleton/pyproject.toml +45 -0
- aso-0.2.0/skeleton/resources/css/app.css +138 -0
- aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/auth/authenticated_session_controller.ts +54 -0
- aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/auth/confirmable_password_controller.ts +39 -0
- aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/auth/email_verification_notification_controller.ts +23 -0
- aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/auth/email_verification_prompt_controller.ts +22 -0
- aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/auth/new_password_controller.ts +42 -0
- aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/auth/password_reset_link_controller.ts +39 -0
- aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/auth/registered_user_controller.ts +39 -0
- aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/auth/verify_email_controller.ts +25 -0
- aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/dashboard_controller.ts +24 -0
- aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/settings/profile_controller.ts +54 -0
- aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/settings/security_controller.ts +39 -0
- aso-0.2.0/skeleton/resources/js/app.tsx +39 -0
- aso-0.2.0/skeleton/resources/js/components/app-content.tsx +23 -0
- aso-0.2.0/skeleton/resources/js/components/app-header.tsx +249 -0
- aso-0.2.0/skeleton/resources/js/components/app-logo-icon.tsx +16 -0
- aso-0.2.0/skeleton/resources/js/components/app-logo.tsx +21 -0
- aso-0.2.0/skeleton/resources/js/components/app-shell.tsx +22 -0
- aso-0.2.0/skeleton/resources/js/components/app-sidebar-header.tsx +19 -0
- aso-0.2.0/skeleton/resources/js/components/app-sidebar.tsx +66 -0
- aso-0.2.0/skeleton/resources/js/components/appearance-tabs.tsx +47 -0
- aso-0.2.0/skeleton/resources/js/components/breadcrumbs.tsx +51 -0
- aso-0.2.0/skeleton/resources/js/components/delete-user.tsx +122 -0
- aso-0.2.0/skeleton/resources/js/components/heading.tsx +27 -0
- aso-0.2.0/skeleton/resources/js/components/input-error.tsx +18 -0
- aso-0.2.0/skeleton/resources/js/components/nav-footer.tsx +50 -0
- aso-0.2.0/skeleton/resources/js/components/nav-main.tsx +37 -0
- aso-0.2.0/skeleton/resources/js/components/nav-user.tsx +59 -0
- aso-0.2.0/skeleton/resources/js/components/password-input.tsx +38 -0
- aso-0.2.0/skeleton/resources/js/components/text-link.tsx +24 -0
- aso-0.2.0/skeleton/resources/js/components/ui/alert.tsx +67 -0
- aso-0.2.0/skeleton/resources/js/components/ui/avatar.tsx +52 -0
- aso-0.2.0/skeleton/resources/js/components/ui/breadcrumb.tsx +110 -0
- aso-0.2.0/skeleton/resources/js/components/ui/button.tsx +59 -0
- aso-0.2.0/skeleton/resources/js/components/ui/card.tsx +69 -0
- aso-0.2.0/skeleton/resources/js/components/ui/checkbox.tsx +31 -0
- aso-0.2.0/skeleton/resources/js/components/ui/dialog.tsx +134 -0
- aso-0.2.0/skeleton/resources/js/components/ui/dropdown-menu.tsx +256 -0
- aso-0.2.0/skeleton/resources/js/components/ui/icon.tsx +15 -0
- aso-0.2.0/skeleton/resources/js/components/ui/input.tsx +22 -0
- aso-0.2.0/skeleton/resources/js/components/ui/label.tsx +23 -0
- aso-0.2.0/skeleton/resources/js/components/ui/navigation-menu.tsx +169 -0
- aso-0.2.0/skeleton/resources/js/components/ui/placeholder-pattern.tsx +21 -0
- aso-0.2.0/skeleton/resources/js/components/ui/separator.tsx +27 -0
- aso-0.2.0/skeleton/resources/js/components/ui/sheet.tsx +138 -0
- aso-0.2.0/skeleton/resources/js/components/ui/sidebar.tsx +720 -0
- aso-0.2.0/skeleton/resources/js/components/ui/skeleton.tsx +14 -0
- aso-0.2.0/skeleton/resources/js/components/ui/sonner.tsx +28 -0
- aso-0.2.0/skeleton/resources/js/components/ui/spinner.tsx +17 -0
- aso-0.2.0/skeleton/resources/js/components/ui/tooltip.tsx +56 -0
- aso-0.2.0/skeleton/resources/js/components/user-info.tsx +33 -0
- aso-0.2.0/skeleton/resources/js/components/user-menu-content.tsx +65 -0
- aso-0.2.0/skeleton/resources/js/hooks/use-appearance.tsx +116 -0
- aso-0.2.0/skeleton/resources/js/hooks/use-current-url.ts +84 -0
- aso-0.2.0/skeleton/resources/js/hooks/use-flash-toast.ts +30 -0
- aso-0.2.0/skeleton/resources/js/hooks/use-initials.tsx +27 -0
- aso-0.2.0/skeleton/resources/js/hooks/use-mobile-navigation.ts +11 -0
- aso-0.2.0/skeleton/resources/js/hooks/use-mobile.tsx +37 -0
- aso-0.2.0/skeleton/resources/js/layouts/app/app-header-layout.tsx +17 -0
- aso-0.2.0/skeleton/resources/js/layouts/app/app-sidebar-layout.tsx +21 -0
- aso-0.2.0/skeleton/resources/js/layouts/app-layout.tsx +17 -0
- aso-0.2.0/skeleton/resources/js/layouts/auth/auth-card-layout.tsx +49 -0
- aso-0.2.0/skeleton/resources/js/layouts/auth/auth-simple-layout.tsx +39 -0
- aso-0.2.0/skeleton/resources/js/layouts/auth/auth-split-layout.tsx +45 -0
- aso-0.2.0/skeleton/resources/js/layouts/auth-layout.tsx +18 -0
- aso-0.2.0/skeleton/resources/js/layouts/settings/layout.tsx +79 -0
- aso-0.2.0/skeleton/resources/js/lib/utils.ts +13 -0
- aso-0.2.0/skeleton/resources/js/pages/auth/confirm-password.tsx +54 -0
- aso-0.2.0/skeleton/resources/js/pages/auth/forgot-password.tsx +70 -0
- aso-0.2.0/skeleton/resources/js/pages/auth/login.tsx +116 -0
- aso-0.2.0/skeleton/resources/js/pages/auth/register.tsx +122 -0
- aso-0.2.0/skeleton/resources/js/pages/auth/reset-password.tsx +98 -0
- aso-0.2.0/skeleton/resources/js/pages/auth/verify-email.tsx +47 -0
- aso-0.2.0/skeleton/resources/js/pages/dashboard.tsx +38 -0
- aso-0.2.0/skeleton/resources/js/pages/error.tsx +46 -0
- aso-0.2.0/skeleton/resources/js/pages/settings/appearance.tsx +34 -0
- aso-0.2.0/skeleton/resources/js/pages/settings/profile.tsx +134 -0
- aso-0.2.0/skeleton/resources/js/pages/settings/security.tsx +135 -0
- aso-0.2.0/skeleton/resources/js/pages/welcome.tsx +96 -0
- aso-0.2.0/skeleton/resources/js/routes/appearance/index.ts +20 -0
- aso-0.2.0/skeleton/resources/js/routes/index.ts +79 -0
- aso-0.2.0/skeleton/resources/js/routes/login/index.ts +19 -0
- aso-0.2.0/skeleton/resources/js/routes/password/confirm/index.ts +19 -0
- aso-0.2.0/skeleton/resources/js/routes/password/index.ts +81 -0
- aso-0.2.0/skeleton/resources/js/routes/profile/index.ts +48 -0
- aso-0.2.0/skeleton/resources/js/routes/register/index.ts +19 -0
- aso-0.2.0/skeleton/resources/js/routes/security/index.ts +20 -0
- aso-0.2.0/skeleton/resources/js/routes/user-password/index.ts +19 -0
- aso-0.2.0/skeleton/resources/js/routes/verification/index.ts +52 -0
- aso-0.2.0/skeleton/resources/js/types/auth.ts +16 -0
- aso-0.2.0/skeleton/resources/js/types/global.d.ts +32 -0
- aso-0.2.0/skeleton/resources/js/types/index.ts +5 -0
- aso-0.2.0/skeleton/resources/js/types/navigation.ts +16 -0
- aso-0.2.0/skeleton/resources/js/types/ui.ts +23 -0
- aso-0.2.0/skeleton/resources/js/types/vite-env.d.ts +1 -0
- aso-0.2.0/skeleton/resources/js/wayfinder/index.ts +150 -0
- aso-0.2.0/skeleton/resources/views/app.html +27 -0
- aso-0.2.0/skeleton/resources/views/mail/layout.html +20 -0
- aso-0.2.0/skeleton/routes/api.py +7 -0
- aso-0.2.0/skeleton/routes/auth.py +56 -0
- aso-0.2.0/skeleton/routes/console.py +1 -0
- aso-0.2.0/skeleton/routes/settings.py +27 -0
- aso-0.2.0/skeleton/routes/web.py +15 -0
- aso-0.2.0/skeleton/storage/app/public/.gitkeep +0 -0
- aso-0.2.0/skeleton/storage/framework/cache/.gitkeep +0 -0
- aso-0.2.0/skeleton/storage/logs/.gitkeep +0 -0
- aso-0.2.0/skeleton/tests/architecture/test_architecture.py +5 -0
- aso-0.2.0/skeleton/tests/conftest.py +16 -0
- aso-0.2.0/skeleton/tests/feature/auth/test_authentication.py +45 -0
- aso-0.2.0/skeleton/tests/feature/auth/test_email_verification.py +48 -0
- aso-0.2.0/skeleton/tests/feature/auth/test_password_confirmation.py +20 -0
- aso-0.2.0/skeleton/tests/feature/auth/test_password_reset.py +56 -0
- aso-0.2.0/skeleton/tests/feature/auth/test_registration.py +38 -0
- aso-0.2.0/skeleton/tests/feature/settings/test_password_update.py +38 -0
- aso-0.2.0/skeleton/tests/feature/settings/test_profile_update.py +61 -0
- aso-0.2.0/skeleton/tsconfig.json +20 -0
- aso-0.2.0/skeleton/vite/aso.ts +132 -0
- aso-0.2.0/skeleton/vite.config.ts +29 -0
- aso-0.2.0/src/aso/__init__.py +3 -0
- aso-0.2.0/src/aso/auth/__init__.py +33 -0
- aso-0.2.0/src/aso/auth/authenticatable.py +49 -0
- aso-0.2.0/src/aso/auth/events.py +68 -0
- aso-0.2.0/src/aso/auth/features.py +15 -0
- aso-0.2.0/src/aso/auth/gate.py +187 -0
- aso-0.2.0/src/aso/auth/guard.py +247 -0
- aso-0.2.0/src/aso/auth/mail.py +61 -0
- aso-0.2.0/src/aso/auth/middleware.py +281 -0
- aso-0.2.0/src/aso/auth/password_broker.py +121 -0
- aso-0.2.0/src/aso/cache/__init__.py +18 -0
- aso-0.2.0/src/aso/cache/file.py +162 -0
- aso-0.2.0/src/aso/cache/manager.py +169 -0
- aso-0.2.0/src/aso/cache/memory.py +57 -0
- aso-0.2.0/src/aso/cache/redis_store.py +55 -0
- aso-0.2.0/src/aso/config/__init__.py +130 -0
- aso-0.2.0/src/aso/console/__init__.py +25 -0
- aso-0.2.0/src/aso/console/boot.py +88 -0
- aso-0.2.0/src/aso/console/cli.py +207 -0
- aso-0.2.0/src/aso/console/command.py +79 -0
- aso-0.2.0/src/aso/console/commands/__init__.py +35 -0
- aso-0.2.0/src/aso/console/commands/core.py +312 -0
- aso-0.2.0/src/aso/console/commands/db.py +169 -0
- aso-0.2.0/src/aso/console/commands/doctor.py +243 -0
- aso-0.2.0/src/aso/console/commands/key.py +51 -0
- aso-0.2.0/src/aso/console/commands/make.py +843 -0
- aso-0.2.0/src/aso/console/commands/migrate.py +138 -0
- aso-0.2.0/src/aso/console/commands/new.py +232 -0
- aso-0.2.0/src/aso/console/commands/queue.py +110 -0
- aso-0.2.0/src/aso/console/commands/route.py +44 -0
- aso-0.2.0/src/aso/console/commands/routes_generate.py +80 -0
- aso-0.2.0/src/aso/console/commands/schedule.py +92 -0
- aso-0.2.0/src/aso/console/commands/seed.py +30 -0
- aso-0.2.0/src/aso/console/commands/session.py +22 -0
- aso-0.2.0/src/aso/console/commands/storage.py +22 -0
- aso-0.2.0/src/aso/console/commands/test.py +62 -0
- aso-0.2.0/src/aso/console/io.py +83 -0
- aso-0.2.0/src/aso/console/migrations.py +399 -0
- aso-0.2.0/src/aso/console/registry.py +231 -0
- aso-0.2.0/src/aso/console/schedule.py +173 -0
- aso-0.2.0/src/aso/console/signature.py +114 -0
- aso-0.2.0/src/aso/console/stubs/agents_md.stub +1 -0
- aso-0.2.0/src/aso/console/stubs/command.stub +1 -0
- aso-0.2.0/src/aso/console/stubs/controller.stub +1 -0
- aso-0.2.0/src/aso/console/stubs/event.stub +1 -0
- aso-0.2.0/src/aso/console/stubs/factory.stub +1 -0
- aso-0.2.0/src/aso/console/stubs/job.stub +1 -0
- aso-0.2.0/src/aso/console/stubs/listener.stub +1 -0
- aso-0.2.0/src/aso/console/stubs/mail.stub +1 -0
- aso-0.2.0/src/aso/console/stubs/mail_view.stub +1 -0
- aso-0.2.0/src/aso/console/stubs/middleware.stub +1 -0
- aso-0.2.0/src/aso/console/stubs/model.stub +1 -0
- aso-0.2.0/src/aso/console/stubs/page.stub +1 -0
- aso-0.2.0/src/aso/console/stubs/policy.stub +1 -0
- aso-0.2.0/src/aso/console/stubs/request.stub +1 -0
- aso-0.2.0/src/aso/console/stubs/seeder.stub +1 -0
- aso-0.2.0/src/aso/console/stubs/test.stub +1 -0
- aso-0.2.0/src/aso/console/support.py +18 -0
- aso-0.2.0/src/aso/context.py +67 -0
- aso-0.2.0/src/aso/database/__init__.py +45 -0
- aso-0.2.0/src/aso/database/builder.py +678 -0
- aso-0.2.0/src/aso/database/db.py +110 -0
- aso-0.2.0/src/aso/database/engine.py +217 -0
- aso-0.2.0/src/aso/database/factory.py +196 -0
- aso-0.2.0/src/aso/database/middleware.py +19 -0
- aso-0.2.0/src/aso/database/model.py +560 -0
- aso-0.2.0/src/aso/database/pagination.py +326 -0
- aso-0.2.0/src/aso/database/relationships.py +165 -0
- aso-0.2.0/src/aso/database/scope.py +174 -0
- aso-0.2.0/src/aso/database/seeder.py +67 -0
- aso-0.2.0/src/aso/database/types.py +160 -0
- aso-0.2.0/src/aso/events/__init__.py +24 -0
- aso-0.2.0/src/aso/events/event.py +128 -0
- aso-0.2.0/src/aso/events/listener_job.py +50 -0
- aso-0.2.0/src/aso/exceptions/__init__.py +45 -0
- aso-0.2.0/src/aso/exceptions/debug.py +104 -0
- aso-0.2.0/src/aso/exceptions/handler.py +366 -0
- aso-0.2.0/src/aso/exceptions/types.py +210 -0
- aso-0.2.0/src/aso/foundation/__init__.py +37 -0
- aso-0.2.0/src/aso/foundation/application.py +227 -0
- aso-0.2.0/src/aso/foundation/exceptions_config.py +49 -0
- aso-0.2.0/src/aso/foundation/middleware_config.py +141 -0
- aso-0.2.0/src/aso/foundation/paths.py +49 -0
- aso-0.2.0/src/aso/foundation/stack.py +165 -0
- aso-0.2.0/src/aso/http/__init__.py +36 -0
- aso-0.2.0/src/aso/http/controller.py +35 -0
- aso-0.2.0/src/aso/http/encoding.py +58 -0
- aso-0.2.0/src/aso/http/method_spoofing.py +72 -0
- aso-0.2.0/src/aso/http/middleware.py +149 -0
- aso-0.2.0/src/aso/http/request.py +284 -0
- aso-0.2.0/src/aso/http/responses.py +203 -0
- aso-0.2.0/src/aso/inertia/__init__.py +28 -0
- aso-0.2.0/src/aso/inertia/history.py +22 -0
- aso-0.2.0/src/aso/inertia/json_encode.py +45 -0
- aso-0.2.0/src/aso/inertia/middleware.py +108 -0
- aso-0.2.0/src/aso/inertia/property.py +23 -0
- aso-0.2.0/src/aso/inertia/props.py +150 -0
- aso-0.2.0/src/aso/inertia/response.py +390 -0
- aso-0.2.0/src/aso/inertia/root.py +40 -0
- aso-0.2.0/src/aso/inertia/shared.py +18 -0
- aso-0.2.0/src/aso/inertia/vite.py +150 -0
- aso-0.2.0/src/aso/log/__init__.py +10 -0
- aso-0.2.0/src/aso/log/manager.py +246 -0
- aso-0.2.0/src/aso/log/testing.py +59 -0
- aso-0.2.0/src/aso/mail/__init__.py +39 -0
- aso-0.2.0/src/aso/mail/drivers.py +138 -0
- aso-0.2.0/src/aso/mail/mailable.py +98 -0
- aso-0.2.0/src/aso/mail/manager.py +215 -0
- aso-0.2.0/src/aso/mail/queued_mail.py +24 -0
- aso-0.2.0/src/aso/mail/rendering.py +101 -0
- aso-0.2.0/src/aso/mail/resources/views/mail/layout.html +20 -0
- aso-0.2.0/src/aso/queue/__init__.py +39 -0
- aso-0.2.0/src/aso/queue/drivers.py +98 -0
- aso-0.2.0/src/aso/queue/failed.py +100 -0
- aso-0.2.0/src/aso/queue/job.py +90 -0
- aso-0.2.0/src/aso/queue/manager.py +257 -0
- aso-0.2.0/src/aso/queue/serialization.py +76 -0
- aso-0.2.0/src/aso/queue/worker.py +117 -0
- aso-0.2.0/src/aso/rate_limiting/__init__.py +20 -0
- aso-0.2.0/src/aso/rate_limiting/limit.py +40 -0
- aso-0.2.0/src/aso/rate_limiting/limiter.py +79 -0
- aso-0.2.0/src/aso/rate_limiting/middleware.py +73 -0
- aso-0.2.0/src/aso/routing/__init__.py +16 -0
- aso-0.2.0/src/aso/routing/paths.py +118 -0
- aso-0.2.0/src/aso/routing/pipeline.py +204 -0
- aso-0.2.0/src/aso/routing/registry.py +701 -0
- aso-0.2.0/src/aso/routing/signed.py +95 -0
- aso-0.2.0/src/aso/routing/static.py +42 -0
- aso-0.2.0/src/aso/routing/ts_routes.py +482 -0
- aso-0.2.0/src/aso/routing/url.py +65 -0
- aso-0.2.0/src/aso/security/__init__.py +9 -0
- aso-0.2.0/src/aso/security/crypt.py +57 -0
- aso-0.2.0/src/aso/security/hash.py +55 -0
- aso-0.2.0/src/aso/security/keys.py +66 -0
- aso-0.2.0/src/aso/session/__init__.py +40 -0
- aso-0.2.0/src/aso/session/configuration.py +54 -0
- aso-0.2.0/src/aso/session/drivers.py +239 -0
- aso-0.2.0/src/aso/session/forgery.py +157 -0
- aso-0.2.0/src/aso/session/middleware.py +161 -0
- aso-0.2.0/src/aso/session/store.py +255 -0
- aso-0.2.0/src/aso/storage/__init__.py +19 -0
- aso-0.2.0/src/aso/storage/manager.py +167 -0
- aso-0.2.0/src/aso/support/__init__.py +7 -0
- aso-0.2.0/src/aso/support/str_helpers.py +30 -0
- aso-0.2.0/src/aso/testing/__init__.py +31 -0
- aso-0.2.0/src/aso/testing/arch/__init__.py +12 -0
- aso-0.2.0/src/aso/testing/arch/_ast_utils.py +223 -0
- aso-0.2.0/src/aso/testing/arch/_preset.py +411 -0
- aso-0.2.0/src/aso/testing/arch/_selection.py +429 -0
- aso-0.2.0/src/aso/testing/client.py +305 -0
- aso-0.2.0/src/aso/testing/database.py +90 -0
- aso-0.2.0/src/aso/testing/inertia_assert.py +235 -0
- aso-0.2.0/src/aso/testing/options.py +27 -0
- aso-0.2.0/src/aso/testing/plugin.py +164 -0
- aso-0.2.0/src/aso/testing/response.py +358 -0
- aso-0.2.0/src/aso/validation/__init__.py +33 -0
- aso-0.2.0/src/aso/validation/form_request.py +259 -0
- aso-0.2.0/src/aso/validation/input.py +100 -0
- aso-0.2.0/src/aso/validation/messages.py +218 -0
- aso-0.2.0/src/aso/validation/rules.py +247 -0
- aso-0.2.0/src/aso/validation/uploaded_file.py +82 -0
- aso-0.2.0/tests/auth/conftest.py +92 -0
- aso-0.2.0/tests/auth/test_auth_app_stack.py +292 -0
- aso-0.2.0/tests/auth/test_events.py +56 -0
- aso-0.2.0/tests/auth/test_features.py +17 -0
- aso-0.2.0/tests/auth/test_gate.py +198 -0
- aso-0.2.0/tests/auth/test_guard_unit.py +129 -0
- aso-0.2.0/tests/auth/test_password_broker_unit.py +161 -0
- aso-0.2.0/tests/cache/conftest.py +14 -0
- aso-0.2.0/tests/cache/test_file_driver.py +100 -0
- aso-0.2.0/tests/cache/test_manager_unit.py +86 -0
- aso-0.2.0/tests/cache/test_memory_driver.py +135 -0
- aso-0.2.0/tests/cache/test_redis_driver.py +96 -0
- aso-0.2.0/tests/conftest.py +70 -0
- aso-0.2.0/tests/console/conftest.py +50 -0
- aso-0.2.0/tests/console/test_console_agents_update.py +64 -0
- aso-0.2.0/tests/console/test_console_cli.py +67 -0
- aso-0.2.0/tests/console/test_console_command.py +103 -0
- aso-0.2.0/tests/console/test_console_core_commands.py +136 -0
- aso-0.2.0/tests/console/test_console_doctor.py +43 -0
- aso-0.2.0/tests/console/test_console_handover.py +73 -0
- aso-0.2.0/tests/console/test_console_migrations.py +85 -0
- aso-0.2.0/tests/console/test_console_queue_commands.py +99 -0
- aso-0.2.0/tests/console/test_console_scheduler.py +145 -0
- aso-0.2.0/tests/console/test_console_seed_command.py +108 -0
- aso-0.2.0/tests/console/test_console_signature.py +83 -0
- aso-0.2.0/tests/console/test_console_user_commands.py +86 -0
- aso-0.2.0/tests/database/conftest.py +111 -0
- aso-0.2.0/tests/database/test_builder_bulk_chunk.py +64 -0
- aso-0.2.0/tests/database/test_builder_order_limit.py +144 -0
- aso-0.2.0/tests/database/test_builder_terminal.py +125 -0
- aso-0.2.0/tests/database/test_builder_where.py +169 -0
- aso-0.2.0/tests/database/test_db_raw.py +85 -0
- aso-0.2.0/tests/database/test_model_basics.py +365 -0
- aso-0.2.0/tests/database/test_model_crud.py +149 -0
- aso-0.2.0/tests/database/test_pagination.py +333 -0
- aso-0.2.0/tests/database/test_relationships.py +369 -0
- aso-0.2.0/tests/database/test_soft_deletes.py +85 -0
- aso-0.2.0/tests/database/test_transactions.py +266 -0
- aso-0.2.0/tests/database/test_types.py +69 -0
- aso-0.2.0/tests/database/test_uuids_ulids.py +54 -0
- aso-0.2.0/tests/e2e/README.md +14 -0
- aso-0.2.0/tests/e2e/browser.mjs +97 -0
- aso-0.2.0/tests/events/_event_fixtures.py +97 -0
- aso-0.2.0/tests/events/conftest.py +47 -0
- aso-0.2.0/tests/events/test_event_after_commit.py +53 -0
- aso-0.2.0/tests/events/test_event_dispatch.py +54 -0
- aso-0.2.0/tests/events/test_event_fake.py +70 -0
- aso-0.2.0/tests/events/test_order_shipment_stack.py +81 -0
- aso-0.2.0/tests/events/test_queued_listener.py +130 -0
- aso-0.2.0/tests/events/test_registry.py +53 -0
- aso-0.2.0/tests/exceptions/conftest.py +65 -0
- aso-0.2.0/tests/exceptions/test_builtin_conversions.py +134 -0
- aso-0.2.0/tests/exceptions/test_debug_page.py +25 -0
- aso-0.2.0/tests/exceptions/test_inertia_shared_data_fallback.py +43 -0
- aso-0.2.0/tests/exceptions/test_report_and_config.py +86 -0
- aso-0.2.0/tests/factories/conftest.py +69 -0
- aso-0.2.0/tests/factories/test_factory_core.py +169 -0
- aso-0.2.0/tests/factories/test_factory_relations.py +74 -0
- aso-0.2.0/tests/factories/test_seeder.py +81 -0
- aso-0.2.0/tests/fixtures/arch_bad/app/bootstrap_helpers.py +5 -0
- aso-0.2.0/tests/fixtures/arch_bad/app/config_leak.py +5 -0
- aso-0.2.0/tests/fixtures/arch_bad/app/http/controllers/post_controller.py +11 -0
- aso-0.2.0/tests/fixtures/arch_bad/app/http/controllers/profile_controller.py +9 -0
- aso-0.2.0/tests/fixtures/arch_bad/app/http/middleware/custom_middleware.py +7 -0
- aso-0.2.0/tests/fixtures/arch_bad/app/http/requests/profile_update_payload.py +7 -0
- aso-0.2.0/tests/fixtures/arch_bad/app/jobs/notify_job.py +13 -0
- aso-0.2.0/tests/fixtures/arch_bad/app/legacy_inertia.py +3 -0
- aso-0.2.0/tests/fixtures/arch_bad/app/models/comment.py +7 -0
- aso-0.2.0/tests/fixtures/arch_bad/app/models/post.py +10 -0
- aso-0.2.0/tests/fixtures/arch_bad/app/services/debug_helper.py +5 -0
- aso-0.2.0/tests/fixtures/arch_bad/app/services/search_service.py +8 -0
- aso-0.2.0/tests/fixtures/arch_bad/resources/js/pages/posts/index.tsx +3 -0
- aso-0.2.0/tests/fixtures/arch_bad/routes/web.py +7 -0
- aso-0.2.0/tests/fixtures/arch_good/app/http/controllers/post_controller.py +14 -0
- aso-0.2.0/tests/fixtures/arch_good/app/http/requests/store_post_request.py +7 -0
- aso-0.2.0/tests/fixtures/arch_good/app/jobs/send_welcome_email.py +11 -0
- aso-0.2.0/tests/fixtures/arch_good/app/models/post.py +9 -0
- aso-0.2.0/tests/fixtures/arch_good/resources/js/pages/posts/index.tsx +3 -0
- aso-0.2.0/tests/fixtures/arch_good/routes/web.py +12 -0
- aso-0.2.0/tests/fixtures/auth_app/app/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/auth_app/app/http/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/auth_app/app/http/controllers/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/auth_app/app/http/controllers/confirm_password_controller.py +23 -0
- aso-0.2.0/tests/fixtures/auth_app/app/http/controllers/dashboard_controller.py +20 -0
- aso-0.2.0/tests/fixtures/auth_app/app/http/controllers/password_reset_controller.py +32 -0
- aso-0.2.0/tests/fixtures/auth_app/app/http/controllers/post_controller.py +13 -0
- aso-0.2.0/tests/fixtures/auth_app/app/http/controllers/registration_controller.py +29 -0
- aso-0.2.0/tests/fixtures/auth_app/app/http/controllers/session_controller.py +56 -0
- aso-0.2.0/tests/fixtures/auth_app/app/http/controllers/verification_controller.py +34 -0
- aso-0.2.0/tests/fixtures/auth_app/app/listeners/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/auth_app/app/listeners/send_email_verification_notification.py +17 -0
- aso-0.2.0/tests/fixtures/auth_app/app/models/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/auth_app/app/models/post.py +10 -0
- aso-0.2.0/tests/fixtures/auth_app/app/models/user.py +21 -0
- aso-0.2.0/tests/fixtures/auth_app/app/policies/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/auth_app/app/policies/post_policy.py +12 -0
- aso-0.2.0/tests/fixtures/auth_app/bootstrap/app.py +15 -0
- aso-0.2.0/tests/fixtures/auth_app/config/app.py +7 -0
- aso-0.2.0/tests/fixtures/auth_app/config/auth.py +26 -0
- aso-0.2.0/tests/fixtures/auth_app/config/database.py +6 -0
- aso-0.2.0/tests/fixtures/auth_app/config/mail.py +14 -0
- aso-0.2.0/tests/fixtures/auth_app/config/session.py +4 -0
- aso-0.2.0/tests/fixtures/auth_app/routes/api.py +0 -0
- aso-0.2.0/tests/fixtures/auth_app/routes/web.py +43 -0
- aso-0.2.0/tests/fixtures/blog/app/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/blog/app/http/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/blog/app/http/controllers/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/blog/app/http/controllers/post_controller.py +27 -0
- aso-0.2.0/tests/fixtures/blog/app/http/middleware/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/blog/app/http/middleware/handle_inertia_requests.py +7 -0
- aso-0.2.0/tests/fixtures/blog/app/http/requests/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/blog/app/http/requests/store_post_request.py +7 -0
- aso-0.2.0/tests/fixtures/blog/app/models/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/blog/app/models/post.py +7 -0
- aso-0.2.0/tests/fixtures/blog/bootstrap/app.py +16 -0
- aso-0.2.0/tests/fixtures/blog/config/app.py +7 -0
- aso-0.2.0/tests/fixtures/blog/config/database.py +6 -0
- aso-0.2.0/tests/fixtures/blog/config/session.py +4 -0
- aso-0.2.0/tests/fixtures/blog/resources/js/pages/error.tsx +0 -0
- aso-0.2.0/tests/fixtures/blog/resources/js/pages/posts/create.tsx +0 -0
- aso-0.2.0/tests/fixtures/blog/resources/js/pages/posts/index.tsx +0 -0
- aso-0.2.0/tests/fixtures/blog/resources/views/app.html +3 -0
- aso-0.2.0/tests/fixtures/blog/routes/api.py +5 -0
- aso-0.2.0/tests/fixtures/blog/routes/web.py +9 -0
- aso-0.2.0/tests/fixtures/console_app/app/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/console_app/app/console/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/console_app/app/console/commands/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/console_app/app/models/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/console_app/app/models/post.py +10 -0
- aso-0.2.0/tests/fixtures/console_app/bootstrap/app.py +9 -0
- aso-0.2.0/tests/fixtures/console_app/config/app.py +7 -0
- aso-0.2.0/tests/fixtures/console_app/config/database.py +6 -0
- aso-0.2.0/tests/fixtures/console_app/config/session.py +2 -0
- aso-0.2.0/tests/fixtures/console_app/routes/web.py +8 -0
- aso-0.2.0/tests/fixtures/errors/app/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/errors/app/exceptions/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/errors/app/exceptions/app_error.py +11 -0
- aso-0.2.0/tests/fixtures/errors/app/exceptions/orders.py +19 -0
- aso-0.2.0/tests/fixtures/errors/app/exceptions/payment_declined.py +19 -0
- aso-0.2.0/tests/fixtures/errors/app/http/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/errors/app/http/controllers/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/errors/app/http/controllers/error_controller.py +57 -0
- aso-0.2.0/tests/fixtures/errors/app/http/middleware/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/errors/app/http/middleware/crash_before_inertia.py +20 -0
- aso-0.2.0/tests/fixtures/errors/app/http/middleware/handle_inertia_requests.py +7 -0
- aso-0.2.0/tests/fixtures/errors/app/http/requests/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/errors/app/http/requests/store_thing_request.py +8 -0
- aso-0.2.0/tests/fixtures/errors/bootstrap/app.py +46 -0
- aso-0.2.0/tests/fixtures/errors/config/app.py +7 -0
- aso-0.2.0/tests/fixtures/errors/config/session.py +4 -0
- aso-0.2.0/tests/fixtures/errors/resources/js/pages/error.tsx +0 -0
- aso-0.2.0/tests/fixtures/errors/resources/views/app.html +3 -0
- aso-0.2.0/tests/fixtures/errors/routes/api.py +9 -0
- aso-0.2.0/tests/fixtures/errors/routes/web.py +21 -0
- aso-0.2.0/tests/fixtures/factories_app/app/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/factories_app/app/models/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/factories_app/app/models/post.py +13 -0
- aso-0.2.0/tests/fixtures/factories_app/app/models/user.py +16 -0
- aso-0.2.0/tests/fixtures/factories_app/database/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/factories_app/database/factories/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/factories_app/database/factories/post_factory.py +13 -0
- aso-0.2.0/tests/fixtures/factories_app/database/factories/user_factory.py +20 -0
- aso-0.2.0/tests/fixtures/inertia_app/app/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/inertia_app/app/http/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/inertia_app/app/http/controllers/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/inertia_app/app/http/controllers/errors_controller.py +16 -0
- aso-0.2.0/tests/fixtures/inertia_app/app/http/controllers/page_controller.py +66 -0
- aso-0.2.0/tests/fixtures/inertia_app/app/http/middleware/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/inertia_app/app/http/middleware/handle_inertia_requests.py +17 -0
- aso-0.2.0/tests/fixtures/inertia_app/app/http/middleware/share_feature_flag.py +10 -0
- aso-0.2.0/tests/fixtures/inertia_app/app/http/requests/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/inertia_app/app/http/requests/invite_member_request.py +8 -0
- aso-0.2.0/tests/fixtures/inertia_app/app/http/requests/store_thing_request.py +7 -0
- aso-0.2.0/tests/fixtures/inertia_app/bootstrap/app.py +17 -0
- aso-0.2.0/tests/fixtures/inertia_app/config/app.py +7 -0
- aso-0.2.0/tests/fixtures/inertia_app/config/session.py +4 -0
- aso-0.2.0/tests/fixtures/inertia_app/resources/js/pages/error.tsx +0 -0
- aso-0.2.0/tests/fixtures/inertia_app/resources/js/pages/errors/create.tsx +0 -0
- aso-0.2.0/tests/fixtures/inertia_app/resources/js/pages/kitchen.tsx +0 -0
- aso-0.2.0/tests/fixtures/inertia_app/resources/js/pages/shared.tsx +0 -0
- aso-0.2.0/tests/fixtures/inertia_app/resources/views/app.html +12 -0
- aso-0.2.0/tests/fixtures/inertia_app/routes/web.py +17 -0
- aso-0.2.0/tests/fixtures/orders_app/app/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/orders_app/app/events/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/orders_app/app/events/order_shipped.py +6 -0
- aso-0.2.0/tests/fixtures/orders_app/app/http/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/orders_app/app/http/controllers/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/orders_app/app/http/controllers/order_shipment_controller.py +42 -0
- aso-0.2.0/tests/fixtures/orders_app/app/listeners/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/orders_app/app/listeners/log_shipment.py +14 -0
- aso-0.2.0/tests/fixtures/orders_app/app/listeners/send_shipment_notification.py +27 -0
- aso-0.2.0/tests/fixtures/orders_app/app/mail/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/orders_app/app/mail/shipment_confirmation.py +14 -0
- aso-0.2.0/tests/fixtures/orders_app/app/models/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/orders_app/app/models/order.py +8 -0
- aso-0.2.0/tests/fixtures/orders_app/bootstrap/app.py +17 -0
- aso-0.2.0/tests/fixtures/orders_app/config/app.py +7 -0
- aso-0.2.0/tests/fixtures/orders_app/config/database.py +6 -0
- aso-0.2.0/tests/fixtures/orders_app/config/mail.py +14 -0
- aso-0.2.0/tests/fixtures/orders_app/config/session.py +4 -0
- aso-0.2.0/tests/fixtures/orders_app/resources/views/mail/shipment_confirmation.html +6 -0
- aso-0.2.0/tests/fixtures/orders_app/routes/api.py +10 -0
- aso-0.2.0/tests/fixtures/orders_app/routes/web.py +0 -0
- aso-0.2.0/tests/fixtures/plugin_project/app/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/plugin_project/app/http/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/plugin_project/app/http/controllers/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/plugin_project/app/http/controllers/post_controller.py +23 -0
- aso-0.2.0/tests/fixtures/plugin_project/app/http/middleware/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/plugin_project/app/http/middleware/handle_inertia_requests.py +7 -0
- aso-0.2.0/tests/fixtures/plugin_project/app/models/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/plugin_project/app/models/post.py +11 -0
- aso-0.2.0/tests/fixtures/plugin_project/app/models/user.py +15 -0
- aso-0.2.0/tests/fixtures/plugin_project/bootstrap/app.py +16 -0
- aso-0.2.0/tests/fixtures/plugin_project/checks_feature.py +43 -0
- aso-0.2.0/tests/fixtures/plugin_project/config/app.py +7 -0
- aso-0.2.0/tests/fixtures/plugin_project/config/auth.py +9 -0
- aso-0.2.0/tests/fixtures/plugin_project/config/database.py +6 -0
- aso-0.2.0/tests/fixtures/plugin_project/config/session.py +4 -0
- aso-0.2.0/tests/fixtures/plugin_project/pytest.ini +6 -0
- aso-0.2.0/tests/fixtures/plugin_project/resources/js/pages/posts/index.tsx +3 -0
- aso-0.2.0/tests/fixtures/plugin_project/resources/views/app.html +3 -0
- aso-0.2.0/tests/fixtures/plugin_project/routes/web.py +6 -0
- aso-0.2.0/tests/fixtures/routing_app/app/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/comment_controller.py +34 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/convert_controller.py +49 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/fallback_controller.py +7 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/gated_controller.py +15 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/group_controller.py +20 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/misc_controller.py +190 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/ping_invokable.py +8 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/post_controller.py +36 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/stub_controllers.py +40 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/middleware/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/middleware/bodypeek.py +15 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/middleware/handle_inertia_requests.py +7 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/middleware/header_mutator.py +12 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/middleware/raiser.py +11 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/middleware/recording.py +45 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/middleware/role.py +13 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/middleware/short_circuit.py +11 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/requests/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/requests/store_post_request.py +8 -0
- aso-0.2.0/tests/fixtures/routing_app/app/http/requests/update_post_request.py +7 -0
- aso-0.2.0/tests/fixtures/routing_app/app/models/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/routing_app/app/models/comment.py +11 -0
- aso-0.2.0/tests/fixtures/routing_app/app/models/post.py +10 -0
- aso-0.2.0/tests/fixtures/routing_app/bootstrap/app.py +38 -0
- aso-0.2.0/tests/fixtures/routing_app/config/app.py +7 -0
- aso-0.2.0/tests/fixtures/routing_app/config/database.py +6 -0
- aso-0.2.0/tests/fixtures/routing_app/config/session.py +4 -0
- aso-0.2.0/tests/fixtures/routing_app/resources/js/pages/about.tsx +0 -0
- aso-0.2.0/tests/fixtures/routing_app/resources/views/app.html +3 -0
- aso-0.2.0/tests/fixtures/routing_app/routes/api.py +10 -0
- aso-0.2.0/tests/fixtures/routing_app/routes/included.py +7 -0
- aso-0.2.0/tests/fixtures/routing_app/routes/web.py +149 -0
- aso-0.2.0/tests/fixtures/session_app/bootstrap/app.py +20 -0
- aso-0.2.0/tests/fixtures/session_app/config/app.py +7 -0
- aso-0.2.0/tests/fixtures/session_app/config/session.py +12 -0
- aso-0.2.0/tests/fixtures/session_app/resources/js/pages/error.tsx +0 -0
- aso-0.2.0/tests/fixtures/session_app/resources/views/app.html +3 -0
- aso-0.2.0/tests/fixtures/session_app/routes/web.py +60 -0
- aso-0.2.0/tests/fixtures/testing_app/app/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/testing_app/app/http/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/testing_app/app/http/controllers/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/testing_app/app/http/controllers/api_post_controller.py +19 -0
- aso-0.2.0/tests/fixtures/testing_app/app/http/controllers/post_controller.py +36 -0
- aso-0.2.0/tests/fixtures/testing_app/app/http/middleware/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/testing_app/app/http/middleware/handle_inertia_requests.py +15 -0
- aso-0.2.0/tests/fixtures/testing_app/app/http/requests/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/testing_app/app/http/requests/store_post_request.py +10 -0
- aso-0.2.0/tests/fixtures/testing_app/app/models/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/testing_app/app/models/post.py +13 -0
- aso-0.2.0/tests/fixtures/testing_app/app/models/user.py +16 -0
- aso-0.2.0/tests/fixtures/testing_app/bootstrap/app.py +16 -0
- aso-0.2.0/tests/fixtures/testing_app/config/app.py +7 -0
- aso-0.2.0/tests/fixtures/testing_app/config/auth.py +9 -0
- aso-0.2.0/tests/fixtures/testing_app/config/database.py +6 -0
- aso-0.2.0/tests/fixtures/testing_app/config/session.py +4 -0
- aso-0.2.0/tests/fixtures/testing_app/resources/js/pages/error.tsx +3 -0
- aso-0.2.0/tests/fixtures/testing_app/resources/js/pages/posts/create.tsx +3 -0
- aso-0.2.0/tests/fixtures/testing_app/resources/js/pages/posts/index.tsx +3 -0
- aso-0.2.0/tests/fixtures/testing_app/resources/js/pages/posts/show.tsx +3 -0
- aso-0.2.0/tests/fixtures/testing_app/resources/views/app.html +3 -0
- aso-0.2.0/tests/fixtures/testing_app/routes/api.py +7 -0
- aso-0.2.0/tests/fixtures/testing_app/routes/web.py +9 -0
- aso-0.2.0/tests/fixtures/throttle_app/app/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/throttle_app/app/http/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/throttle_app/app/http/controllers/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/throttle_app/app/http/controllers/ping_controller.py +14 -0
- aso-0.2.0/tests/fixtures/throttle_app/app/http/middleware/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/throttle_app/bootstrap/app.py +16 -0
- aso-0.2.0/tests/fixtures/throttle_app/config/app.py +7 -0
- aso-0.2.0/tests/fixtures/throttle_app/config/database.py +6 -0
- aso-0.2.0/tests/fixtures/throttle_app/config/session.py +4 -0
- aso-0.2.0/tests/fixtures/throttle_app/routes/api.py +5 -0
- aso-0.2.0/tests/fixtures/throttle_app/routes/web.py +7 -0
- aso-0.2.0/tests/fixtures/validation_app/app/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/validation_app/app/http/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/validation_app/app/http/controllers/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/validation_app/app/http/controllers/debug_controller.py +13 -0
- aso-0.2.0/tests/fixtures/validation_app/app/http/controllers/form_controller.py +77 -0
- aso-0.2.0/tests/fixtures/validation_app/app/http/middleware/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/validation_app/app/http/middleware/handle_inertia_requests.py +7 -0
- aso-0.2.0/tests/fixtures/validation_app/app/http/requests/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/validation_app/app/http/requests/order_request.py +13 -0
- aso-0.2.0/tests/fixtures/validation_app/app/http/requests/profile_requests.py +50 -0
- aso-0.2.0/tests/fixtures/validation_app/app/http/requests/store_post_request.py +47 -0
- aso-0.2.0/tests/fixtures/validation_app/app/models/__init__.py +0 -0
- aso-0.2.0/tests/fixtures/validation_app/app/models/team.py +9 -0
- aso-0.2.0/tests/fixtures/validation_app/app/models/user.py +10 -0
- aso-0.2.0/tests/fixtures/validation_app/bootstrap/app.py +16 -0
- aso-0.2.0/tests/fixtures/validation_app/config/app.py +7 -0
- aso-0.2.0/tests/fixtures/validation_app/config/database.py +6 -0
- aso-0.2.0/tests/fixtures/validation_app/config/session.py +4 -0
- aso-0.2.0/tests/fixtures/validation_app/resources/js/pages/error.tsx +0 -0
- aso-0.2.0/tests/fixtures/validation_app/resources/js/pages/forms/create.tsx +0 -0
- aso-0.2.0/tests/fixtures/validation_app/resources/views/app.html +3 -0
- aso-0.2.0/tests/fixtures/validation_app/routes/api.py +6 -0
- aso-0.2.0/tests/fixtures/validation_app/routes/web.py +22 -0
- aso-0.2.0/tests/generators/conftest.py +99 -0
- aso-0.2.0/tests/generators/test_make_controller.py +80 -0
- aso-0.2.0/tests/generators/test_make_misc.py +167 -0
- aso-0.2.0/tests/generators/test_make_model.py +131 -0
- aso-0.2.0/tests/generators/test_overwrite_guard.py +56 -0
- aso-0.2.0/tests/generators/test_stub_publish.py +56 -0
- aso-0.2.0/tests/http/conftest.py +73 -0
- aso-0.2.0/tests/http/test_controller.py +41 -0
- aso-0.2.0/tests/http/test_encoding_unit.py +64 -0
- aso-0.2.0/tests/http/test_method_spoofing.py +44 -0
- aso-0.2.0/tests/http/test_middleware_adapter.py +52 -0
- aso-0.2.0/tests/http/test_request_api.py +108 -0
- aso-0.2.0/tests/http/test_response_builder.py +56 -0
- aso-0.2.0/tests/http/test_responses.py +152 -0
- aso-0.2.0/tests/http/test_return_value_conversion.py +50 -0
- aso-0.2.0/tests/inertia/conftest.py +56 -0
- aso-0.2.0/tests/inertia/test_errors_and_flash.py +82 -0
- aso-0.2.0/tests/inertia/test_history_and_location.py +43 -0
- aso-0.2.0/tests/inertia/test_json_encode.py +65 -0
- aso-0.2.0/tests/inertia/test_prop_categories.py +154 -0
- aso-0.2.0/tests/inertia/test_props_unit.py +103 -0
- aso-0.2.0/tests/inertia/test_shared_and_version.py +64 -0
- aso-0.2.0/tests/inertia/test_vite.py +149 -0
- aso-0.2.0/tests/inertia/test_vite_helpers_build_css.py +22 -0
- aso-0.2.0/tests/log/test_capture_and_configure.py +69 -0
- aso-0.2.0/tests/log/test_channels.py +99 -0
- aso-0.2.0/tests/log/test_context_and_redaction.py +66 -0
- aso-0.2.0/tests/log/test_log_facade.py +65 -0
- aso-0.2.0/tests/mail/conftest.py +37 -0
- aso-0.2.0/tests/mail/test_mail_after_commit.py +55 -0
- aso-0.2.0/tests/mail/test_mail_drivers.py +192 -0
- aso-0.2.0/tests/mail/test_mail_fake.py +110 -0
- aso-0.2.0/tests/mail/test_mailable.py +160 -0
- aso-0.2.0/tests/mail/test_pending_mail.py +243 -0
- aso-0.2.0/tests/mail/test_rendering.py +38 -0
- aso-0.2.0/tests/queue/_jobs.py +104 -0
- aso-0.2.0/tests/queue/conftest.py +51 -0
- aso-0.2.0/tests/queue/test_after_commit.py +45 -0
- aso-0.2.0/tests/queue/test_after_response.py +37 -0
- aso-0.2.0/tests/queue/test_dispatch.py +62 -0
- aso-0.2.0/tests/queue/test_drivers_config.py +51 -0
- aso-0.2.0/tests/queue/test_failed_jobs.py +52 -0
- aso-0.2.0/tests/queue/test_fake.py +60 -0
- aso-0.2.0/tests/queue/test_retries_and_worker.py +82 -0
- aso-0.2.0/tests/queue/test_serialization.py +48 -0
- aso-0.2.0/tests/queue/test_worker_restart.py +30 -0
- aso-0.2.0/tests/rate_limiting/conftest.py +52 -0
- aso-0.2.0/tests/rate_limiting/test_limiter_unit.py +54 -0
- aso-0.2.0/tests/rate_limiting/test_throttle_feature.py +77 -0
- aso-0.2.0/tests/routing/conftest.py +73 -0
- aso-0.2.0/tests/routing/test_feature_middleware.py +99 -0
- aso-0.2.0/tests/routing/test_feature_resources_and_binding.py +147 -0
- aso-0.2.0/tests/routing/test_feature_signed_and_misc.py +100 -0
- aso-0.2.0/tests/routing/test_feature_verbs_and_groups.py +107 -0
- aso-0.2.0/tests/routing/test_paths_unit.py +85 -0
- aso-0.2.0/tests/routing/test_pipeline_unit.py +143 -0
- aso-0.2.0/tests/routing/test_public_files.py +26 -0
- aso-0.2.0/tests/routing/test_registry_unit.py +275 -0
- aso-0.2.0/tests/security/test_crypt.py +64 -0
- aso-0.2.0/tests/security/test_hash.py +38 -0
- aso-0.2.0/tests/security/test_keys.py +50 -0
- aso-0.2.0/tests/session/test_drivers.py +227 -0
- aso-0.2.0/tests/session/test_middleware_integration.py +168 -0
- aso-0.2.0/tests/session/test_store.py +233 -0
- aso-0.2.0/tests/skeleton/test_new_command.py +70 -0
- aso-0.2.0/tests/storage/conftest.py +14 -0
- aso-0.2.0/tests/storage/test_disk_unit.py +104 -0
- aso-0.2.0/tests/storage/test_storage_link.py +60 -0
- aso-0.2.0/tests/storage/test_uploaded_file_store.py +59 -0
- aso-0.2.0/tests/support/test_slug.py +33 -0
- aso-0.2.0/tests/test_spine_loop.py +124 -0
- aso-0.2.0/tests/testing/conftest.py +87 -0
- aso-0.2.0/tests/testing/test_arch_rules.py +162 -0
- aso-0.2.0/tests/testing/test_client_assertions.py +82 -0
- aso-0.2.0/tests/testing/test_client_requests.py +123 -0
- aso-0.2.0/tests/testing/test_database_assertions.py +52 -0
- aso-0.2.0/tests/testing/test_inertia_assert_unit.py +75 -0
- aso-0.2.0/tests/testing/test_inertia_assertions.py +123 -0
- aso-0.2.0/tests/testing/test_plugin_end_to_end.py +50 -0
- aso-0.2.0/tests/testing/test_test_command.py +52 -0
- aso-0.2.0/tests/ts_routes/conftest.py +37 -0
- aso-0.2.0/tests/ts_routes/test_generator.py +139 -0
- aso-0.2.0/tests/validation/conftest.py +58 -0
- aso-0.2.0/tests/validation/test_input.py +55 -0
- aso-0.2.0/tests/validation/test_integration.py +269 -0
- aso-0.2.0/tests/validation/test_messages.py +133 -0
- aso-0.2.0/tests/validation/test_rules_unit.py +115 -0
- aso-0.2.0/tests/validation/test_uploaded_file.py +58 -0
- aso-0.2.0/uv.lock +2387 -0
aso-0.2.0/.gitignore
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
.venv/
|
|
5
|
+
*.egg-info/
|
|
6
|
+
dist/
|
|
7
|
+
build/
|
|
8
|
+
.pytest_cache/
|
|
9
|
+
.ruff_cache/
|
|
10
|
+
.mypy_cache/
|
|
11
|
+
.coverage
|
|
12
|
+
htmlcov/
|
|
13
|
+
|
|
14
|
+
# Env / local
|
|
15
|
+
.env
|
|
16
|
+
*.sqlite
|
|
17
|
+
*.sqlite-journal
|
|
18
|
+
|
|
19
|
+
# Node
|
|
20
|
+
node_modules/
|
|
21
|
+
public/build/
|
|
22
|
+
public/hot
|
|
23
|
+
|
|
24
|
+
# Generated by `aso routes:generate` (T-28) -- rewritten from scratch on every run
|
|
25
|
+
resources/js/routes/
|
|
26
|
+
resources/js/actions/
|
|
27
|
+
resources/js/wayfinder/
|
|
28
|
+
|
|
29
|
+
# The skeleton template is never a buildable project in this repo: its own venv/lock/db are
|
|
30
|
+
# throwaway artifacts from running its tests, not framework state to track.
|
|
31
|
+
/skeleton/.venv/
|
|
32
|
+
/skeleton/uv.lock
|
|
33
|
+
/skeleton/database/database.sqlite
|
|
34
|
+
/skeleton/database/database.sqlite-*
|
|
35
|
+
|
|
36
|
+
# Spikes
|
|
37
|
+
spikes/**/server.log
|
|
38
|
+
spikes/**/server.pid
|
|
39
|
+
spikes/**/version.txt
|
|
40
|
+
spikes/**/package-lock.json
|
|
41
|
+
spikes/uv.lock
|
|
42
|
+
|
|
43
|
+
# Logs written by fixture apps (contents only, so a tracked `storage/logs/.gitkeep` survives --
|
|
44
|
+
# a directory-matching pattern here would exclude the whole directory and git cannot re-include
|
|
45
|
+
# a file whose parent directory is excluded)
|
|
46
|
+
storage/logs/*
|
|
47
|
+
**/storage/logs/*
|
|
48
|
+
!**/storage/logs/.gitkeep
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
aso-0.2.0/BUILD.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Building Aso (for contributors and coding agents)
|
|
2
|
+
|
|
3
|
+
The framework is built **spec-first**: every feature has a reviewed guide page in the separate
|
|
4
|
+
docs repo (`../docs/guide/T-xx-*.md`). The code must match the page. When the page and your idea
|
|
5
|
+
disagree, the page wins; if the page is wrong or impossible, say so in your report instead of
|
|
6
|
+
silently doing something else.
|
|
7
|
+
|
|
8
|
+
Spec precedence: `docs/plan/DECISIONS.md` > `docs/plan/LARAVEL-MAP.md` (names and import paths)
|
|
9
|
+
> the guide page > `docs/plan/RESEARCH-BASELINE.md`. Spike write-ups: `docs/research/spikes/`.
|
|
10
|
+
|
|
11
|
+
## Layout
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
src/aso/
|
|
15
|
+
context.py per-request context (ContextVar). Read its docstring first.
|
|
16
|
+
config/ env(), config()
|
|
17
|
+
foundation/ Application.configure()...create(), MiddlewareConfig, ExceptionsConfig,
|
|
18
|
+
stack.py (group stacks + exception boundaries), paths
|
|
19
|
+
exceptions/ types.py = EVERY framework exception class; handler.py = report/render
|
|
20
|
+
routing/ http/ session/ database/ inertia/ validation/ auth/ ... one package per area
|
|
21
|
+
tests/
|
|
22
|
+
test_spine_loop.py end-to-end loop through the real stack; must always pass
|
|
23
|
+
fixtures/blog/ a tiny app used by end-to-end tests
|
|
24
|
+
<package>/ each package's own tests
|
|
25
|
+
spikes/ Phase 0 proof-of-concepts (reference code, not imported)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## How a request flows (read `foundation/stack.py`)
|
|
29
|
+
|
|
30
|
+
Global layers: `RequestContextMiddleware` → `MethodSpoofing` → `DatabaseScope` → user globals →
|
|
31
|
+
router. Each matched route's ASGI app is wrapped with its group's stack: for `web`,
|
|
32
|
+
`Boundary(StartSession(Boundary(AuthenticateSession(Boundary(PreventRequestForgery(Boundary(
|
|
33
|
+
HandleInertiaRequests(Boundary(endpoint))))))))`. Exceptions are rendered by the nearest
|
|
34
|
+
boundary through `aso.exceptions.handler`. Unknown URLs hit catch-all fallback routes
|
|
35
|
+
registered last, so they still pass through the group stack.
|
|
36
|
+
|
|
37
|
+
## Contracts between packages
|
|
38
|
+
|
|
39
|
+
- **Request context** (`aso.context`): `current()` / `require()`; fields `request`,
|
|
40
|
+
`group`, `session`, `user`, `inertia`, `shared`, `route`, `route_params`, `extras`. The table in
|
|
41
|
+
its docstring says which package writes which field. Only write your own fields.
|
|
42
|
+
- **Exceptions**: raise the classes in `aso.exceptions.types`; re-export them from your
|
|
43
|
+
package at the LARAVEL-MAP §3 path. Never define a second class with the same meaning.
|
|
44
|
+
- **Session**: other packages use `aso.session.session()` and the `Session` methods named in
|
|
45
|
+
T-18 only.
|
|
46
|
+
- **Database**: other packages use `Model`, `DB` and `aso.database.scope` only.
|
|
47
|
+
- **Framework middleware is pure ASGI** (D-025). Never use `BaseHTTPMiddleware`.
|
|
48
|
+
- **Lazy imports across packages** inside functions, to avoid import cycles at package import time.
|
|
49
|
+
|
|
50
|
+
## Rules for agents
|
|
51
|
+
|
|
52
|
+
1. Work **only inside the files and folders your task names**. If you need a change elsewhere
|
|
53
|
+
(a shared file such as `context.py`, `foundation/*`, `exceptions/types.py`, or another
|
|
54
|
+
package), do not make it: describe the exact change in your final report.
|
|
55
|
+
2. Do **not** commit, push, publish, or touch `../cli`, `../docs` or git state. The reviewer
|
|
56
|
+
commits.
|
|
57
|
+
3. Public names and import paths come from LARAVEL-MAP. Do not invent public APIs; private
|
|
58
|
+
helpers (`_name`) are fine.
|
|
59
|
+
4. Write tests in `tests/<package>/` with pytest (async tests need no decorator: asyncio auto
|
|
60
|
+
mode). Test behaviour through the real stack where it matters (see `tests/test_spine_loop.py`
|
|
61
|
+
and its fixture app), plus unit tests.
|
|
62
|
+
5. Before finishing run `uv run pytest -q` (everything, not just yours) and
|
|
63
|
+
`uv run ruff check src tests`. Report the results honestly, including failures you could not fix.
|
|
64
|
+
6. Keep the code's style: type hints, short docstrings that say *why*, no print statements.
|
|
65
|
+
7. Spec gaps: choose the most Laravel-like behaviour, implement it, and list it in your report under
|
|
66
|
+
"Decisions I made".
|
|
67
|
+
|
|
68
|
+
## Commands
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
uv sync # install
|
|
72
|
+
uv run pytest -q # all tests
|
|
73
|
+
uv run ruff check src tests # lint
|
|
74
|
+
DB_URL=postgresql+asyncpg://postgres:secret@127.0.0.1:55432/aso uv run pytest -q tests/database
|
|
75
|
+
```
|
aso-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: aso
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: The Aso framework: a Laravel-style web framework for Python (FastAPI + Inertia.js + an artisan-like CLI)
|
|
5
|
+
Project-URL: Homepage, https://github.com/Ibnu-Afdel/Aso
|
|
6
|
+
Project-URL: Source, https://github.com/Ibnu-Afdel/Aso
|
|
7
|
+
Project-URL: Issues, https://github.com/Ibnu-Afdel/Aso/issues
|
|
8
|
+
Author-email: Abubeker Afdel <ibnuafdel@gmail.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
Requires-Python: >=3.12
|
|
11
|
+
Requires-Dist: aiosmtplib>=5.1
|
|
12
|
+
Requires-Dist: aiosqlite>=0.22
|
|
13
|
+
Requires-Dist: alembic>=1.20
|
|
14
|
+
Requires-Dist: croniter<7,>=6.2
|
|
15
|
+
Requires-Dist: cryptography>=50
|
|
16
|
+
Requires-Dist: faker>=40
|
|
17
|
+
Requires-Dist: fastapi<0.144,>=0.143
|
|
18
|
+
Requires-Dist: httpx2>=2.13
|
|
19
|
+
Requires-Dist: inflect>=7.5
|
|
20
|
+
Requires-Dist: itsdangerous>=2.2
|
|
21
|
+
Requires-Dist: jinja2>=3.1.6
|
|
22
|
+
Requires-Dist: pwdlib[argon2]>=0.3.1
|
|
23
|
+
Requires-Dist: pydantic[email]<2.15,>=2.14
|
|
24
|
+
Requires-Dist: python-dotenv>=1.2.4
|
|
25
|
+
Requires-Dist: python-multipart>=0.0.20
|
|
26
|
+
Requires-Dist: sqlalchemy[asyncio]<2.2,>=2.1.4
|
|
27
|
+
Requires-Dist: starlette<1.8,>=1.7
|
|
28
|
+
Requires-Dist: typer<0.28,>=0.27
|
|
29
|
+
Requires-Dist: uvicorn[standard]>=0.54
|
|
30
|
+
Requires-Dist: watchfiles>=1.0
|
|
31
|
+
Provides-Extra: mysql
|
|
32
|
+
Requires-Dist: asyncmy>=0.2.16; extra == 'mysql'
|
|
33
|
+
Provides-Extra: pgsql
|
|
34
|
+
Requires-Dist: asyncpg>=0.32; extra == 'pgsql'
|
|
35
|
+
Provides-Extra: redis
|
|
36
|
+
Requires-Dist: redis>=8.1; extra == 'redis'
|
|
37
|
+
Requires-Dist: taskiq-redis>=1.2.4; extra == 'redis'
|
|
38
|
+
Requires-Dist: taskiq>=0.13; extra == 'redis'
|
|
39
|
+
Provides-Extra: testing
|
|
40
|
+
Requires-Dist: pytest-asyncio<1.5,>=1.4; extra == 'testing'
|
|
41
|
+
Requires-Dist: pytest>=9.1; extra == 'testing'
|
|
42
|
+
Description-Content-Type: text/markdown
|
|
43
|
+
|
|
44
|
+
# Aso
|
|
45
|
+
|
|
46
|
+
The Aso framework is a Laravel-style web framework for Python: **FastAPI** on the backend,
|
|
47
|
+
**Inertia.js v3 + React** on the frontend, and an artisan-like CLI (`aso make:controller`,
|
|
48
|
+
`aso migrate`, ...).
|
|
49
|
+
|
|
50
|
+
> **Status: early (0.2.0).** It works end to end, but expect rough edges and breaking changes.
|
|
51
|
+
> Versions up to 0.1.1 were published as `fastogram`; that package is retired.
|
|
52
|
+
> The previous Telegram bot template (0.0.x, FastAPI + aiogram) is kept under the tag
|
|
53
|
+
> `legacy-telegram-template` and on the `release/public-ready` branch.
|
|
54
|
+
|
|
55
|
+
## Try it
|
|
56
|
+
|
|
57
|
+
You need [uv](https://docs.astral.sh/uv/), Node 22+ and npm.
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
uvx aso new myapp # like `laravel new myapp`
|
|
61
|
+
cd myapp
|
|
62
|
+
uv run aso dev # server + Vite + route watcher
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Open http://127.0.0.1:8000, register, and you're in the React starter kit (dashboard, settings,
|
|
66
|
+
password reset, email verification). In local mode mail goes to `storage/logs/`.
|
|
67
|
+
|
|
68
|
+
Useful commands: `aso list`, `aso route:list`, `aso make:model Post -mcr`,
|
|
69
|
+
`aso migrate`, `uv run pytest`.
|
|
70
|
+
|
|
71
|
+
## What it looks like
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
# routes/web.py
|
|
75
|
+
with Route.middleware("auth").group():
|
|
76
|
+
Route.get("/posts", [PostController, "index"]).name("posts.index")
|
|
77
|
+
Route.post("/posts", [PostController, "store"]).name("posts.store")
|
|
78
|
+
|
|
79
|
+
# app/http/controllers/post_controller.py
|
|
80
|
+
class PostController(Controller):
|
|
81
|
+
async def index(self):
|
|
82
|
+
return inertia("posts/index", {"posts": await Post.with_("author").latest().paginate(15)})
|
|
83
|
+
|
|
84
|
+
async def store(self, form: StorePostRequest):
|
|
85
|
+
await Post.create(**form.validated(), user_id=auth().id())
|
|
86
|
+
return redirect().route("posts.index").with_flash("success", "Post created.")
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Repository layout
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
src/aso/ the framework library and CLI (published to PyPI as `aso`)
|
|
93
|
+
skeleton/ the app that `aso new` creates (like laravel/laravel)
|
|
94
|
+
tests/ the framework's own tests
|
|
95
|
+
spikes/ Phase 0 proof-of-concept spikes (throwaway)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## License
|
|
99
|
+
|
|
100
|
+
MIT
|
aso-0.2.0/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Aso
|
|
2
|
+
|
|
3
|
+
The Aso framework is a Laravel-style web framework for Python: **FastAPI** on the backend,
|
|
4
|
+
**Inertia.js v3 + React** on the frontend, and an artisan-like CLI (`aso make:controller`,
|
|
5
|
+
`aso migrate`, ...).
|
|
6
|
+
|
|
7
|
+
> **Status: early (0.2.0).** It works end to end, but expect rough edges and breaking changes.
|
|
8
|
+
> Versions up to 0.1.1 were published as `fastogram`; that package is retired.
|
|
9
|
+
> The previous Telegram bot template (0.0.x, FastAPI + aiogram) is kept under the tag
|
|
10
|
+
> `legacy-telegram-template` and on the `release/public-ready` branch.
|
|
11
|
+
|
|
12
|
+
## Try it
|
|
13
|
+
|
|
14
|
+
You need [uv](https://docs.astral.sh/uv/), Node 22+ and npm.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
uvx aso new myapp # like `laravel new myapp`
|
|
18
|
+
cd myapp
|
|
19
|
+
uv run aso dev # server + Vite + route watcher
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Open http://127.0.0.1:8000, register, and you're in the React starter kit (dashboard, settings,
|
|
23
|
+
password reset, email verification). In local mode mail goes to `storage/logs/`.
|
|
24
|
+
|
|
25
|
+
Useful commands: `aso list`, `aso route:list`, `aso make:model Post -mcr`,
|
|
26
|
+
`aso migrate`, `uv run pytest`.
|
|
27
|
+
|
|
28
|
+
## What it looks like
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
# routes/web.py
|
|
32
|
+
with Route.middleware("auth").group():
|
|
33
|
+
Route.get("/posts", [PostController, "index"]).name("posts.index")
|
|
34
|
+
Route.post("/posts", [PostController, "store"]).name("posts.store")
|
|
35
|
+
|
|
36
|
+
# app/http/controllers/post_controller.py
|
|
37
|
+
class PostController(Controller):
|
|
38
|
+
async def index(self):
|
|
39
|
+
return inertia("posts/index", {"posts": await Post.with_("author").latest().paginate(15)})
|
|
40
|
+
|
|
41
|
+
async def store(self, form: StorePostRequest):
|
|
42
|
+
await Post.create(**form.validated(), user_id=auth().id())
|
|
43
|
+
return redirect().route("posts.index").with_flash("success", "Post created.")
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Repository layout
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
src/aso/ the framework library and CLI (published to PyPI as `aso`)
|
|
50
|
+
skeleton/ the app that `aso new` creates (like laravel/laravel)
|
|
51
|
+
tests/ the framework's own tests
|
|
52
|
+
spikes/ Phase 0 proof-of-concept spikes (throwaway)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## License
|
|
56
|
+
|
|
57
|
+
MIT
|
aso-0.2.0/pyproject.toml
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "aso"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "The Aso framework: a Laravel-style web framework for Python (FastAPI + Inertia.js + an artisan-like CLI)"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Abubeker Afdel", email = "ibnuafdel@gmail.com"}
|
|
14
|
+
]
|
|
15
|
+
dependencies = [
|
|
16
|
+
"fastapi>=0.143,<0.144",
|
|
17
|
+
"starlette>=1.7,<1.8",
|
|
18
|
+
"uvicorn[standard]>=0.54",
|
|
19
|
+
"pydantic[email]>=2.14,<2.15",
|
|
20
|
+
"sqlalchemy[asyncio]>=2.1.4,<2.2",
|
|
21
|
+
"aiosqlite>=0.22",
|
|
22
|
+
"alembic>=1.20",
|
|
23
|
+
"typer>=0.27,<0.28",
|
|
24
|
+
"jinja2>=3.1.6",
|
|
25
|
+
"itsdangerous>=2.2",
|
|
26
|
+
"cryptography>=50",
|
|
27
|
+
"pwdlib[argon2]>=0.3.1",
|
|
28
|
+
"python-dotenv>=1.2.4",
|
|
29
|
+
"python-multipart>=0.0.20",
|
|
30
|
+
"inflect>=7.5",
|
|
31
|
+
"faker>=40",
|
|
32
|
+
"aiosmtplib>=5.1",
|
|
33
|
+
"httpx2>=2.13",
|
|
34
|
+
"watchfiles>=1.0",
|
|
35
|
+
"croniter>=6.2,<7",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[project.urls]
|
|
39
|
+
Homepage = "https://github.com/Ibnu-Afdel/Aso"
|
|
40
|
+
Source = "https://github.com/Ibnu-Afdel/Aso"
|
|
41
|
+
Issues = "https://github.com/Ibnu-Afdel/Aso/issues"
|
|
42
|
+
|
|
43
|
+
[project.optional-dependencies]
|
|
44
|
+
pgsql = ["asyncpg>=0.32"]
|
|
45
|
+
mysql = ["asyncmy>=0.2.16"]
|
|
46
|
+
redis = ["redis>=8.1", "taskiq>=0.13", "taskiq-redis>=1.2.4"]
|
|
47
|
+
testing = ["pytest>=9.1", "pytest-asyncio>=1.4,<1.5"]
|
|
48
|
+
|
|
49
|
+
[project.scripts]
|
|
50
|
+
aso = "aso.console.cli:main"
|
|
51
|
+
|
|
52
|
+
[project.entry-points.pytest11]
|
|
53
|
+
aso = "aso.testing.plugin"
|
|
54
|
+
|
|
55
|
+
[dependency-groups]
|
|
56
|
+
dev = [
|
|
57
|
+
"pytest>=9.1",
|
|
58
|
+
"pytest-asyncio>=1.4,<1.5",
|
|
59
|
+
"asyncpg>=0.32",
|
|
60
|
+
"ruff>=0.14",
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
[tool.hatch.build]
|
|
64
|
+
exclude = [
|
|
65
|
+
"**/.venv",
|
|
66
|
+
"**/.venv/**",
|
|
67
|
+
"**/uv.lock",
|
|
68
|
+
"**/database.sqlite",
|
|
69
|
+
"**/database.sqlite-*",
|
|
70
|
+
"**/__pycache__",
|
|
71
|
+
"**/*.py[cod]",
|
|
72
|
+
"**/.pytest_cache",
|
|
73
|
+
"**/.ruff_cache",
|
|
74
|
+
"**/node_modules",
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
[tool.hatch.build.targets.wheel]
|
|
78
|
+
packages = ["src/aso"]
|
|
79
|
+
|
|
80
|
+
# D-022: the app skeleton (`aso new` copies this) ships inside the wheel as
|
|
81
|
+
# `aso/skeleton/`, not as a second top-level package.
|
|
82
|
+
[tool.hatch.build.targets.wheel.force-include]
|
|
83
|
+
"skeleton" = "aso/skeleton"
|
|
84
|
+
|
|
85
|
+
[tool.pytest.ini_options]
|
|
86
|
+
testpaths = ["tests"]
|
|
87
|
+
asyncio_mode = "auto"
|
|
88
|
+
asyncio_default_test_loop_scope = "session"
|
|
89
|
+
asyncio_default_fixture_loop_scope = "session"
|
|
90
|
+
addopts = "-p no:aso"
|
|
91
|
+
markers = [
|
|
92
|
+
"skeleton: exercises `aso new` end-to-end in a subprocess (slow, but still <3 min; part of the default run)",
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
[tool.ruff]
|
|
96
|
+
line-length = 110
|
|
97
|
+
target-version = "py312"
|
|
98
|
+
|
|
99
|
+
[tool.ruff.lint]
|
|
100
|
+
select = ["E", "F", "I", "B", "UP"]
|
|
101
|
+
ignore = ["E501", "UP046", "UP047"]
|
|
102
|
+
|
|
103
|
+
[tool.ruff.lint.isort]
|
|
104
|
+
known-first-party = ["aso"]
|
|
105
|
+
known-local-folder = ["app", "bootstrap", "config", "routes", "database"]
|
|
106
|
+
|
|
107
|
+
[tool.hatch.build.targets.sdist]
|
|
108
|
+
exclude = ["/spikes", "/storage", "/dist", "**/node_modules", "**/.venv"]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
APP_NAME=Aso
|
|
2
|
+
APP_ENV=local
|
|
3
|
+
APP_DEBUG=true
|
|
4
|
+
APP_URL=http://localhost:8000
|
|
5
|
+
APP_KEY=
|
|
6
|
+
APP_TIMEZONE=UTC
|
|
7
|
+
APP_LOCALE=en
|
|
8
|
+
|
|
9
|
+
DB_CONNECTION=sqlite
|
|
10
|
+
DB_DATABASE=database/database.sqlite
|
|
11
|
+
|
|
12
|
+
SESSION_DRIVER=database
|
|
13
|
+
SESSION_LIFETIME=120
|
|
14
|
+
|
|
15
|
+
QUEUE_CONNECTION=sync
|
|
16
|
+
|
|
17
|
+
CACHE_STORE=file
|
|
18
|
+
|
|
19
|
+
MAIL_MAILER=log
|
|
20
|
+
MAIL_HOST=127.0.0.1
|
|
21
|
+
MAIL_PORT=2525
|
|
22
|
+
MAIL_USERNAME=null
|
|
23
|
+
MAIL_PASSWORD=null
|
|
24
|
+
MAIL_SCHEME=null
|
|
25
|
+
MAIL_FROM_ADDRESS=hello@example.com
|
|
26
|
+
MAIL_FROM_NAME="${APP_NAME}"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
APP_NAME=Aso
|
|
2
|
+
APP_ENV=testing
|
|
3
|
+
APP_DEBUG=true
|
|
4
|
+
APP_URL=http://testserver
|
|
5
|
+
APP_KEY=base64:2fl+Ktvkfl+Fuz4Qp/A75G2RTiWVA/ZoKZvp6fiiM10=
|
|
6
|
+
APP_TIMEZONE=UTC
|
|
7
|
+
APP_LOCALE=en
|
|
8
|
+
|
|
9
|
+
DB_CONNECTION=sqlite
|
|
10
|
+
DB_DATABASE=:memory:
|
|
11
|
+
|
|
12
|
+
SESSION_DRIVER=array
|
|
13
|
+
|
|
14
|
+
QUEUE_CONNECTION=sync
|
|
15
|
+
|
|
16
|
+
CACHE_STORE=memory
|
|
17
|
+
|
|
18
|
+
MAIL_MAILER=array
|
|
19
|
+
MAIL_FROM_ADDRESS=hello@example.com
|
|
20
|
+
MAIL_FROM_NAME=Aso
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/.venv
|
|
2
|
+
/node_modules
|
|
3
|
+
/.env
|
|
4
|
+
/database/database.sqlite
|
|
5
|
+
/database/database.sqlite-*
|
|
6
|
+
/public/build
|
|
7
|
+
/public/hot
|
|
8
|
+
/public/storage
|
|
9
|
+
/storage/app/*
|
|
10
|
+
!/storage/app/public
|
|
11
|
+
/storage/app/public/*
|
|
12
|
+
!/storage/app/public/.gitkeep
|
|
13
|
+
/storage/framework/cache/*
|
|
14
|
+
!/storage/framework/cache/.gitkeep
|
|
15
|
+
/storage/logs/*
|
|
16
|
+
!/storage/logs/.gitkeep
|
|
17
|
+
/resources/js/routes
|
|
18
|
+
/resources/js/actions
|
|
19
|
+
/resources/js/wayfinder
|
|
20
|
+
__pycache__/
|
|
21
|
+
*.py[cod]
|
|
22
|
+
.pytest_cache/
|
|
23
|
+
.ruff_cache/
|
|
24
|
+
.coverage
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Instructions for AI Agents
|
|
2
|
+
|
|
3
|
+
You are developing on an Aso project (FastAPI + Inertia.js v3 + React 19).
|
|
4
|
+
Follow these conventions strictly.
|
|
5
|
+
|
|
6
|
+
## 1. Generator First
|
|
7
|
+
Always generate code using `aso make:*` commands rather than writing empty files manually:
|
|
8
|
+
- `aso make:model Post -a --fields="title:string body:text"`
|
|
9
|
+
- `aso make:controller PostController --resource --model=Post --requests`
|
|
10
|
+
- `aso make:request StorePostRequest`
|
|
11
|
+
- `aso make:page posts/index`
|
|
12
|
+
- `aso make:test PostTest`
|
|
13
|
+
|
|
14
|
+
## 2. Architecture Rules (A1-A13)
|
|
15
|
+
The project runs AST-based architecture tests in `tests/architecture/`. Never violate these rules:
|
|
16
|
+
- A1: Controllers must not import `sqlalchemy`. Move queries to model scopes or methods.
|
|
17
|
+
- A2: Models must not import `fastapi`, `starlette`, or `aso.http`. Models must function without HTTP requests.
|
|
18
|
+
- A3: Controller methods must not read raw request input (`request.input()`, `request.json()`). Take a `FormRequest` parameter instead.
|
|
19
|
+
- A4: Pages passed to `inertia("posts/index")` must exist in `resources/js/pages/posts/index.tsx`.
|
|
20
|
+
- A5: Do not import a third-party Inertia adapter (`cross_inertia`, `inertia`, `fastapi_inertia`). Use `aso.inertia`.
|
|
21
|
+
- A6: Never interpolate raw SQL with f-strings, `%`, or `+`. Use parameterized `:name` bindings.
|
|
22
|
+
- A7: Do not use `print()` or `breakpoint()`. Use `from aso.log import log`.
|
|
23
|
+
- A8: Do not subclass `BaseHTTPMiddleware`. Inherit from `aso.http.Middleware`.
|
|
24
|
+
- A9: Do not create manual SQLAlchemy engines or sessions. Use `from aso.database import DB`.
|
|
25
|
+
- A10: Form request classes in `app/http/requests/` must extend `FormRequest` and end with `Request`.
|
|
26
|
+
- A11: Every model in `app/models/` must define `__fillable__` or `__guarded__`.
|
|
27
|
+
- A12: Background jobs in `app/jobs/` must accept scalar IDs in constructors, never model instances.
|
|
28
|
+
- A13: Do not read `os.environ` outside `config/`. Use `from aso.config import config`.
|
|
29
|
+
|
|
30
|
+
## 3. Inertia v3 Conventions
|
|
31
|
+
- Page names are lowercase paths: `inertia("posts/index")`.
|
|
32
|
+
- No Axios. Use Inertia's `<Form>`, `useForm`, `router`, or `useHttp`.
|
|
33
|
+
- On validation failure, web controllers redirect back; they never return 422 JSON.
|
|
34
|
+
- Never hard-code URLs in TSX. Import route helpers from `@/routes/...` (run `aso routes:generate`).
|
|
35
|
+
- Pages never wrap themselves in `<AppLayout>`; pass breadcrumbs with `Page.layout = { breadcrumbs }`.
|
|
36
|
+
- Flash messages arrive in `usePage().flash`. Never add `flash` to `share()`.
|
|
37
|
+
|
|
38
|
+
## 4. Backend habits
|
|
39
|
+
- Every write action (store, update, destroy) ends with `redirect(...).with_flash("success", ...)`.
|
|
40
|
+
- Call `await self.authorize(...)` before changing a model the user might not own.
|
|
41
|
+
- Eager load relations with `with_("author")` or `await post.load("author")`. Unloaded relations raise `LazyLoadingViolation`.
|
|
42
|
+
- Everything that touches the database is `async`: `await Post.find(1)`, `await post.save()`.
|
|
43
|
+
- Group multi-step writes in `async with DB.transaction():`.
|
|
44
|
+
- Paginate lists (`.paginate(15)`); never `get()` an unbounded table for a page.
|
|
45
|
+
- Jobs take ids, never models; reload in `handle()`.
|
|
46
|
+
|
|
47
|
+
## 5. Before you finish
|
|
48
|
+
- `aso test` passes, including `tests/architecture/`.
|
|
49
|
+
- New routes have a feature test: happy path, validation failure, authorization failure.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Laravel React Starter Kit
|
|
2
|
+
|
|
3
|
+
The React side of this kit (layouts, components, pages, hooks under `resources/js/`) is ported
|
|
4
|
+
from the [Laravel React starter kit](https://github.com/laravel/react-starter-kit), which is
|
|
5
|
+
MIT-licensed (its `README.md` and `composer.json` say so; the repository has no separate
|
|
6
|
+
`LICENSE` file, checked 2026-10-09). See T-05 ("Licence") in the FastoGram docs.
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
MIT License
|
|
10
|
+
|
|
11
|
+
Copyright (c) Taylor Otwell
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
in the Software without restriction, including without limitation the rights
|
|
16
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
furnished to do so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Every ported file keeps a one-line header comment naming its origin (T-05): layouts, components,
|
|
33
|
+
hooks and pages ported from the kit say so directly; shadcn/ui primitives under
|
|
34
|
+
`resources/js/components/ui/` (vendored inside the kit's repo, not authored by Laravel, but MIT
|
|
35
|
+
either way) say "Ported from the Laravel React starter kit's shadcn/ui primitives".
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Creates a new user from validated registration data (T-38, Fortify's `CreateNewUser`).
|
|
2
|
+
|
|
3
|
+
Edit this to assign default roles, create workspace records, or set other defaults when a user
|
|
4
|
+
signs up. It survives framework/library upgrades because it lives in your own app code.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from app.models.user import User
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class CreateNewUser:
|
|
11
|
+
async def create(self, data: dict) -> User:
|
|
12
|
+
return await User.create(
|
|
13
|
+
name=data["name"],
|
|
14
|
+
email=data["email"].lower(),
|
|
15
|
+
password=data["password"],
|
|
16
|
+
)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""The password rules shared by registration and password reset (T-38, Fortify's
|
|
2
|
+
`PasswordValidationRules` trait).
|
|
3
|
+
|
|
4
|
+
`rule()` is passed to `Password.defaults()` via `config/auth.py`; `description()` builds the
|
|
5
|
+
`passwordRules` help text the Laravel React kit's `register`/`reset-password`/`settings/security`
|
|
6
|
+
pages display under the password field.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from aso.config import config
|
|
10
|
+
from aso.validation import Password
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class PasswordValidationRules:
|
|
14
|
+
def rule(self) -> Password:
|
|
15
|
+
return Password.defaults()
|
|
16
|
+
|
|
17
|
+
def description(self) -> str:
|
|
18
|
+
rules = config("auth.password_rules", {})
|
|
19
|
+
parts = [f"at least {rules.get('min', 8)} characters"]
|
|
20
|
+
if rules.get("letters"):
|
|
21
|
+
parts.append("letters")
|
|
22
|
+
if rules.get("mixed_case"):
|
|
23
|
+
parts.append("upper and lowercase letters")
|
|
24
|
+
if rules.get("numbers"):
|
|
25
|
+
parts.append("at least one number")
|
|
26
|
+
if rules.get("symbols"):
|
|
27
|
+
parts.append("at least one symbol")
|
|
28
|
+
return "Must be " + ", ".join(parts) + "."
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Sets a user's new password (T-38, Fortify's `ResetUserPassword`).
|
|
2
|
+
|
|
3
|
+
`aso.auth.password_broker().reset()` already saves the new password and rotates
|
|
4
|
+
`remember_token` itself (T-38 "How it works"); this action exists so your own reset flow -- or a
|
|
5
|
+
custom `NewPasswordController` -- can reuse the same "how do we set a password" logic instead of
|
|
6
|
+
duplicating it, and so you have one obvious place to extend it (e.g. logging, notifying admins).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from app.models.user import User
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ResetUserPassword:
|
|
13
|
+
async def reset(self, user: User, password: str) -> None:
|
|
14
|
+
user.password = password # the `Hashed` column hashes it on assignment (T-31, T-40)
|
|
15
|
+
await user.save()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Login and logout (T-38)."""
|
|
2
|
+
|
|
3
|
+
from aso.auth import auth, features
|
|
4
|
+
from aso.http import Controller, Request, redirect
|
|
5
|
+
from aso.inertia import clear_history, inertia
|
|
6
|
+
from aso.routing import route
|
|
7
|
+
from aso.session import session
|
|
8
|
+
|
|
9
|
+
from app.http.requests.auth.login_request import LoginRequest
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AuthenticatedSessionController(Controller):
|
|
13
|
+
async def create(self, request: Request):
|
|
14
|
+
return inertia(
|
|
15
|
+
"auth/login",
|
|
16
|
+
{
|
|
17
|
+
"status": session().get("status"),
|
|
18
|
+
"canResetPassword": features.enabled("reset_passwords"),
|
|
19
|
+
},
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
async def store(self, form: LoginRequest):
|
|
23
|
+
await form.authenticate()
|
|
24
|
+
session().regenerate()
|
|
25
|
+
return redirect().intended(route("dashboard"))
|
|
26
|
+
|
|
27
|
+
async def destroy(self):
|
|
28
|
+
await auth().logout()
|
|
29
|
+
session().invalidate()
|
|
30
|
+
session().regenerate_token()
|
|
31
|
+
clear_history()
|
|
32
|
+
return redirect("/")
|