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.
Files changed (770) hide show
  1. aso-0.2.0/.gitignore +48 -0
  2. aso-0.2.0/.python-version +1 -0
  3. aso-0.2.0/BUILD.md +75 -0
  4. aso-0.2.0/PKG-INFO +100 -0
  5. aso-0.2.0/README.md +57 -0
  6. aso-0.2.0/pyproject.toml +108 -0
  7. aso-0.2.0/skeleton/.env.example +26 -0
  8. aso-0.2.0/skeleton/.env.testing +20 -0
  9. aso-0.2.0/skeleton/.gitignore +24 -0
  10. aso-0.2.0/skeleton/AGENTS.md +49 -0
  11. aso-0.2.0/skeleton/LICENSES/laravel-react-starter-kit.md +35 -0
  12. aso-0.2.0/skeleton/app/__init__.py +0 -0
  13. aso-0.2.0/skeleton/app/actions/__init__.py +0 -0
  14. aso-0.2.0/skeleton/app/actions/auth/__init__.py +0 -0
  15. aso-0.2.0/skeleton/app/actions/auth/create_new_user.py +16 -0
  16. aso-0.2.0/skeleton/app/actions/auth/password_validation_rules.py +28 -0
  17. aso-0.2.0/skeleton/app/actions/auth/reset_user_password.py +15 -0
  18. aso-0.2.0/skeleton/app/console/__init__.py +0 -0
  19. aso-0.2.0/skeleton/app/console/commands/__init__.py +0 -0
  20. aso-0.2.0/skeleton/app/exceptions/__init__.py +0 -0
  21. aso-0.2.0/skeleton/app/http/__init__.py +0 -0
  22. aso-0.2.0/skeleton/app/http/controllers/__init__.py +0 -0
  23. aso-0.2.0/skeleton/app/http/controllers/auth/__init__.py +0 -0
  24. aso-0.2.0/skeleton/app/http/controllers/auth/authenticated_session_controller.py +32 -0
  25. aso-0.2.0/skeleton/app/http/controllers/auth/confirmable_password_controller.py +24 -0
  26. aso-0.2.0/skeleton/app/http/controllers/auth/email_verification_notification_controller.py +15 -0
  27. aso-0.2.0/skeleton/app/http/controllers/auth/email_verification_prompt_controller.py +15 -0
  28. aso-0.2.0/skeleton/app/http/controllers/auth/new_password_controller.py +27 -0
  29. aso-0.2.0/skeleton/app/http/controllers/auth/password_reset_link_controller.py +20 -0
  30. aso-0.2.0/skeleton/app/http/controllers/auth/registered_user_controller.py +24 -0
  31. aso-0.2.0/skeleton/app/http/controllers/auth/verify_email_controller.py +23 -0
  32. aso-0.2.0/skeleton/app/http/controllers/dashboard_controller.py +9 -0
  33. aso-0.2.0/skeleton/app/http/controllers/settings/__init__.py +0 -0
  34. aso-0.2.0/skeleton/app/http/controllers/settings/profile_controller.py +39 -0
  35. aso-0.2.0/skeleton/app/http/controllers/settings/security_controller.py +20 -0
  36. aso-0.2.0/skeleton/app/http/middleware/__init__.py +0 -0
  37. aso-0.2.0/skeleton/app/http/middleware/handle_appearance.py +25 -0
  38. aso-0.2.0/skeleton/app/http/middleware/handle_inertia_requests.py +17 -0
  39. aso-0.2.0/skeleton/app/http/requests/__init__.py +0 -0
  40. aso-0.2.0/skeleton/app/http/requests/auth/__init__.py +0 -0
  41. aso-0.2.0/skeleton/app/http/requests/auth/confirm_password_request.py +7 -0
  42. aso-0.2.0/skeleton/app/http/requests/auth/forgot_password_request.py +9 -0
  43. aso-0.2.0/skeleton/app/http/requests/auth/login_request.py +41 -0
  44. aso-0.2.0/skeleton/app/http/requests/auth/register_request.py +16 -0
  45. aso-0.2.0/skeleton/app/http/requests/auth/reset_password_request.py +16 -0
  46. aso-0.2.0/skeleton/app/http/requests/settings/__init__.py +0 -0
  47. aso-0.2.0/skeleton/app/http/requests/settings/delete_user_request.py +10 -0
  48. aso-0.2.0/skeleton/app/http/requests/settings/password_update_request.py +13 -0
  49. aso-0.2.0/skeleton/app/http/requests/settings/profile_update_request.py +13 -0
  50. aso-0.2.0/skeleton/app/jobs/__init__.py +0 -0
  51. aso-0.2.0/skeleton/app/listeners/__init__.py +0 -0
  52. aso-0.2.0/skeleton/app/listeners/send_email_verification_notification.py +14 -0
  53. aso-0.2.0/skeleton/app/mail/__init__.py +0 -0
  54. aso-0.2.0/skeleton/app/models/__init__.py +0 -0
  55. aso-0.2.0/skeleton/app/models/user.py +19 -0
  56. aso-0.2.0/skeleton/app/policies/__init__.py +0 -0
  57. aso-0.2.0/skeleton/bootstrap/app.py +30 -0
  58. aso-0.2.0/skeleton/components.json +21 -0
  59. aso-0.2.0/skeleton/config/app.py +12 -0
  60. aso-0.2.0/skeleton/config/auth.py +50 -0
  61. aso-0.2.0/skeleton/config/cache.py +14 -0
  62. aso-0.2.0/skeleton/config/database.py +34 -0
  63. aso-0.2.0/skeleton/config/filesystems.py +18 -0
  64. aso-0.2.0/skeleton/config/hashing.py +9 -0
  65. aso-0.2.0/skeleton/config/inertia.py +10 -0
  66. aso-0.2.0/skeleton/config/logging.py +18 -0
  67. aso-0.2.0/skeleton/config/mail.py +28 -0
  68. aso-0.2.0/skeleton/config/queue.py +14 -0
  69. aso-0.2.0/skeleton/config/session.py +19 -0
  70. aso-0.2.0/skeleton/database/__init__.py +0 -0
  71. aso-0.2.0/skeleton/database/factories/__init__.py +0 -0
  72. aso-0.2.0/skeleton/database/factories/user_factory.py +22 -0
  73. aso-0.2.0/skeleton/database/migrations/2026_01_01_000000_create_users_table.py +62 -0
  74. aso-0.2.0/skeleton/database/migrations/__init__.py +0 -0
  75. aso-0.2.0/skeleton/database/seeders/__init__.py +0 -0
  76. aso-0.2.0/skeleton/database/seeders/database_seeder.py +8 -0
  77. aso-0.2.0/skeleton/package-lock.json +2625 -0
  78. aso-0.2.0/skeleton/package.json +42 -0
  79. aso-0.2.0/skeleton/public/.gitkeep +0 -0
  80. aso-0.2.0/skeleton/public/favicon.svg +12 -0
  81. aso-0.2.0/skeleton/pyproject.toml +45 -0
  82. aso-0.2.0/skeleton/resources/css/app.css +138 -0
  83. aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/auth/authenticated_session_controller.ts +54 -0
  84. aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/auth/confirmable_password_controller.ts +39 -0
  85. aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/auth/email_verification_notification_controller.ts +23 -0
  86. aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/auth/email_verification_prompt_controller.ts +22 -0
  87. aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/auth/new_password_controller.ts +42 -0
  88. aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/auth/password_reset_link_controller.ts +39 -0
  89. aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/auth/registered_user_controller.ts +39 -0
  90. aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/auth/verify_email_controller.ts +25 -0
  91. aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/dashboard_controller.ts +24 -0
  92. aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/settings/profile_controller.ts +54 -0
  93. aso-0.2.0/skeleton/resources/js/actions/app/http/controllers/settings/security_controller.ts +39 -0
  94. aso-0.2.0/skeleton/resources/js/app.tsx +39 -0
  95. aso-0.2.0/skeleton/resources/js/components/app-content.tsx +23 -0
  96. aso-0.2.0/skeleton/resources/js/components/app-header.tsx +249 -0
  97. aso-0.2.0/skeleton/resources/js/components/app-logo-icon.tsx +16 -0
  98. aso-0.2.0/skeleton/resources/js/components/app-logo.tsx +21 -0
  99. aso-0.2.0/skeleton/resources/js/components/app-shell.tsx +22 -0
  100. aso-0.2.0/skeleton/resources/js/components/app-sidebar-header.tsx +19 -0
  101. aso-0.2.0/skeleton/resources/js/components/app-sidebar.tsx +66 -0
  102. aso-0.2.0/skeleton/resources/js/components/appearance-tabs.tsx +47 -0
  103. aso-0.2.0/skeleton/resources/js/components/breadcrumbs.tsx +51 -0
  104. aso-0.2.0/skeleton/resources/js/components/delete-user.tsx +122 -0
  105. aso-0.2.0/skeleton/resources/js/components/heading.tsx +27 -0
  106. aso-0.2.0/skeleton/resources/js/components/input-error.tsx +18 -0
  107. aso-0.2.0/skeleton/resources/js/components/nav-footer.tsx +50 -0
  108. aso-0.2.0/skeleton/resources/js/components/nav-main.tsx +37 -0
  109. aso-0.2.0/skeleton/resources/js/components/nav-user.tsx +59 -0
  110. aso-0.2.0/skeleton/resources/js/components/password-input.tsx +38 -0
  111. aso-0.2.0/skeleton/resources/js/components/text-link.tsx +24 -0
  112. aso-0.2.0/skeleton/resources/js/components/ui/alert.tsx +67 -0
  113. aso-0.2.0/skeleton/resources/js/components/ui/avatar.tsx +52 -0
  114. aso-0.2.0/skeleton/resources/js/components/ui/breadcrumb.tsx +110 -0
  115. aso-0.2.0/skeleton/resources/js/components/ui/button.tsx +59 -0
  116. aso-0.2.0/skeleton/resources/js/components/ui/card.tsx +69 -0
  117. aso-0.2.0/skeleton/resources/js/components/ui/checkbox.tsx +31 -0
  118. aso-0.2.0/skeleton/resources/js/components/ui/dialog.tsx +134 -0
  119. aso-0.2.0/skeleton/resources/js/components/ui/dropdown-menu.tsx +256 -0
  120. aso-0.2.0/skeleton/resources/js/components/ui/icon.tsx +15 -0
  121. aso-0.2.0/skeleton/resources/js/components/ui/input.tsx +22 -0
  122. aso-0.2.0/skeleton/resources/js/components/ui/label.tsx +23 -0
  123. aso-0.2.0/skeleton/resources/js/components/ui/navigation-menu.tsx +169 -0
  124. aso-0.2.0/skeleton/resources/js/components/ui/placeholder-pattern.tsx +21 -0
  125. aso-0.2.0/skeleton/resources/js/components/ui/separator.tsx +27 -0
  126. aso-0.2.0/skeleton/resources/js/components/ui/sheet.tsx +138 -0
  127. aso-0.2.0/skeleton/resources/js/components/ui/sidebar.tsx +720 -0
  128. aso-0.2.0/skeleton/resources/js/components/ui/skeleton.tsx +14 -0
  129. aso-0.2.0/skeleton/resources/js/components/ui/sonner.tsx +28 -0
  130. aso-0.2.0/skeleton/resources/js/components/ui/spinner.tsx +17 -0
  131. aso-0.2.0/skeleton/resources/js/components/ui/tooltip.tsx +56 -0
  132. aso-0.2.0/skeleton/resources/js/components/user-info.tsx +33 -0
  133. aso-0.2.0/skeleton/resources/js/components/user-menu-content.tsx +65 -0
  134. aso-0.2.0/skeleton/resources/js/hooks/use-appearance.tsx +116 -0
  135. aso-0.2.0/skeleton/resources/js/hooks/use-current-url.ts +84 -0
  136. aso-0.2.0/skeleton/resources/js/hooks/use-flash-toast.ts +30 -0
  137. aso-0.2.0/skeleton/resources/js/hooks/use-initials.tsx +27 -0
  138. aso-0.2.0/skeleton/resources/js/hooks/use-mobile-navigation.ts +11 -0
  139. aso-0.2.0/skeleton/resources/js/hooks/use-mobile.tsx +37 -0
  140. aso-0.2.0/skeleton/resources/js/layouts/app/app-header-layout.tsx +17 -0
  141. aso-0.2.0/skeleton/resources/js/layouts/app/app-sidebar-layout.tsx +21 -0
  142. aso-0.2.0/skeleton/resources/js/layouts/app-layout.tsx +17 -0
  143. aso-0.2.0/skeleton/resources/js/layouts/auth/auth-card-layout.tsx +49 -0
  144. aso-0.2.0/skeleton/resources/js/layouts/auth/auth-simple-layout.tsx +39 -0
  145. aso-0.2.0/skeleton/resources/js/layouts/auth/auth-split-layout.tsx +45 -0
  146. aso-0.2.0/skeleton/resources/js/layouts/auth-layout.tsx +18 -0
  147. aso-0.2.0/skeleton/resources/js/layouts/settings/layout.tsx +79 -0
  148. aso-0.2.0/skeleton/resources/js/lib/utils.ts +13 -0
  149. aso-0.2.0/skeleton/resources/js/pages/auth/confirm-password.tsx +54 -0
  150. aso-0.2.0/skeleton/resources/js/pages/auth/forgot-password.tsx +70 -0
  151. aso-0.2.0/skeleton/resources/js/pages/auth/login.tsx +116 -0
  152. aso-0.2.0/skeleton/resources/js/pages/auth/register.tsx +122 -0
  153. aso-0.2.0/skeleton/resources/js/pages/auth/reset-password.tsx +98 -0
  154. aso-0.2.0/skeleton/resources/js/pages/auth/verify-email.tsx +47 -0
  155. aso-0.2.0/skeleton/resources/js/pages/dashboard.tsx +38 -0
  156. aso-0.2.0/skeleton/resources/js/pages/error.tsx +46 -0
  157. aso-0.2.0/skeleton/resources/js/pages/settings/appearance.tsx +34 -0
  158. aso-0.2.0/skeleton/resources/js/pages/settings/profile.tsx +134 -0
  159. aso-0.2.0/skeleton/resources/js/pages/settings/security.tsx +135 -0
  160. aso-0.2.0/skeleton/resources/js/pages/welcome.tsx +96 -0
  161. aso-0.2.0/skeleton/resources/js/routes/appearance/index.ts +20 -0
  162. aso-0.2.0/skeleton/resources/js/routes/index.ts +79 -0
  163. aso-0.2.0/skeleton/resources/js/routes/login/index.ts +19 -0
  164. aso-0.2.0/skeleton/resources/js/routes/password/confirm/index.ts +19 -0
  165. aso-0.2.0/skeleton/resources/js/routes/password/index.ts +81 -0
  166. aso-0.2.0/skeleton/resources/js/routes/profile/index.ts +48 -0
  167. aso-0.2.0/skeleton/resources/js/routes/register/index.ts +19 -0
  168. aso-0.2.0/skeleton/resources/js/routes/security/index.ts +20 -0
  169. aso-0.2.0/skeleton/resources/js/routes/user-password/index.ts +19 -0
  170. aso-0.2.0/skeleton/resources/js/routes/verification/index.ts +52 -0
  171. aso-0.2.0/skeleton/resources/js/types/auth.ts +16 -0
  172. aso-0.2.0/skeleton/resources/js/types/global.d.ts +32 -0
  173. aso-0.2.0/skeleton/resources/js/types/index.ts +5 -0
  174. aso-0.2.0/skeleton/resources/js/types/navigation.ts +16 -0
  175. aso-0.2.0/skeleton/resources/js/types/ui.ts +23 -0
  176. aso-0.2.0/skeleton/resources/js/types/vite-env.d.ts +1 -0
  177. aso-0.2.0/skeleton/resources/js/wayfinder/index.ts +150 -0
  178. aso-0.2.0/skeleton/resources/views/app.html +27 -0
  179. aso-0.2.0/skeleton/resources/views/mail/layout.html +20 -0
  180. aso-0.2.0/skeleton/routes/api.py +7 -0
  181. aso-0.2.0/skeleton/routes/auth.py +56 -0
  182. aso-0.2.0/skeleton/routes/console.py +1 -0
  183. aso-0.2.0/skeleton/routes/settings.py +27 -0
  184. aso-0.2.0/skeleton/routes/web.py +15 -0
  185. aso-0.2.0/skeleton/storage/app/public/.gitkeep +0 -0
  186. aso-0.2.0/skeleton/storage/framework/cache/.gitkeep +0 -0
  187. aso-0.2.0/skeleton/storage/logs/.gitkeep +0 -0
  188. aso-0.2.0/skeleton/tests/architecture/test_architecture.py +5 -0
  189. aso-0.2.0/skeleton/tests/conftest.py +16 -0
  190. aso-0.2.0/skeleton/tests/feature/auth/test_authentication.py +45 -0
  191. aso-0.2.0/skeleton/tests/feature/auth/test_email_verification.py +48 -0
  192. aso-0.2.0/skeleton/tests/feature/auth/test_password_confirmation.py +20 -0
  193. aso-0.2.0/skeleton/tests/feature/auth/test_password_reset.py +56 -0
  194. aso-0.2.0/skeleton/tests/feature/auth/test_registration.py +38 -0
  195. aso-0.2.0/skeleton/tests/feature/settings/test_password_update.py +38 -0
  196. aso-0.2.0/skeleton/tests/feature/settings/test_profile_update.py +61 -0
  197. aso-0.2.0/skeleton/tsconfig.json +20 -0
  198. aso-0.2.0/skeleton/vite/aso.ts +132 -0
  199. aso-0.2.0/skeleton/vite.config.ts +29 -0
  200. aso-0.2.0/src/aso/__init__.py +3 -0
  201. aso-0.2.0/src/aso/auth/__init__.py +33 -0
  202. aso-0.2.0/src/aso/auth/authenticatable.py +49 -0
  203. aso-0.2.0/src/aso/auth/events.py +68 -0
  204. aso-0.2.0/src/aso/auth/features.py +15 -0
  205. aso-0.2.0/src/aso/auth/gate.py +187 -0
  206. aso-0.2.0/src/aso/auth/guard.py +247 -0
  207. aso-0.2.0/src/aso/auth/mail.py +61 -0
  208. aso-0.2.0/src/aso/auth/middleware.py +281 -0
  209. aso-0.2.0/src/aso/auth/password_broker.py +121 -0
  210. aso-0.2.0/src/aso/cache/__init__.py +18 -0
  211. aso-0.2.0/src/aso/cache/file.py +162 -0
  212. aso-0.2.0/src/aso/cache/manager.py +169 -0
  213. aso-0.2.0/src/aso/cache/memory.py +57 -0
  214. aso-0.2.0/src/aso/cache/redis_store.py +55 -0
  215. aso-0.2.0/src/aso/config/__init__.py +130 -0
  216. aso-0.2.0/src/aso/console/__init__.py +25 -0
  217. aso-0.2.0/src/aso/console/boot.py +88 -0
  218. aso-0.2.0/src/aso/console/cli.py +207 -0
  219. aso-0.2.0/src/aso/console/command.py +79 -0
  220. aso-0.2.0/src/aso/console/commands/__init__.py +35 -0
  221. aso-0.2.0/src/aso/console/commands/core.py +312 -0
  222. aso-0.2.0/src/aso/console/commands/db.py +169 -0
  223. aso-0.2.0/src/aso/console/commands/doctor.py +243 -0
  224. aso-0.2.0/src/aso/console/commands/key.py +51 -0
  225. aso-0.2.0/src/aso/console/commands/make.py +843 -0
  226. aso-0.2.0/src/aso/console/commands/migrate.py +138 -0
  227. aso-0.2.0/src/aso/console/commands/new.py +232 -0
  228. aso-0.2.0/src/aso/console/commands/queue.py +110 -0
  229. aso-0.2.0/src/aso/console/commands/route.py +44 -0
  230. aso-0.2.0/src/aso/console/commands/routes_generate.py +80 -0
  231. aso-0.2.0/src/aso/console/commands/schedule.py +92 -0
  232. aso-0.2.0/src/aso/console/commands/seed.py +30 -0
  233. aso-0.2.0/src/aso/console/commands/session.py +22 -0
  234. aso-0.2.0/src/aso/console/commands/storage.py +22 -0
  235. aso-0.2.0/src/aso/console/commands/test.py +62 -0
  236. aso-0.2.0/src/aso/console/io.py +83 -0
  237. aso-0.2.0/src/aso/console/migrations.py +399 -0
  238. aso-0.2.0/src/aso/console/registry.py +231 -0
  239. aso-0.2.0/src/aso/console/schedule.py +173 -0
  240. aso-0.2.0/src/aso/console/signature.py +114 -0
  241. aso-0.2.0/src/aso/console/stubs/agents_md.stub +1 -0
  242. aso-0.2.0/src/aso/console/stubs/command.stub +1 -0
  243. aso-0.2.0/src/aso/console/stubs/controller.stub +1 -0
  244. aso-0.2.0/src/aso/console/stubs/event.stub +1 -0
  245. aso-0.2.0/src/aso/console/stubs/factory.stub +1 -0
  246. aso-0.2.0/src/aso/console/stubs/job.stub +1 -0
  247. aso-0.2.0/src/aso/console/stubs/listener.stub +1 -0
  248. aso-0.2.0/src/aso/console/stubs/mail.stub +1 -0
  249. aso-0.2.0/src/aso/console/stubs/mail_view.stub +1 -0
  250. aso-0.2.0/src/aso/console/stubs/middleware.stub +1 -0
  251. aso-0.2.0/src/aso/console/stubs/model.stub +1 -0
  252. aso-0.2.0/src/aso/console/stubs/page.stub +1 -0
  253. aso-0.2.0/src/aso/console/stubs/policy.stub +1 -0
  254. aso-0.2.0/src/aso/console/stubs/request.stub +1 -0
  255. aso-0.2.0/src/aso/console/stubs/seeder.stub +1 -0
  256. aso-0.2.0/src/aso/console/stubs/test.stub +1 -0
  257. aso-0.2.0/src/aso/console/support.py +18 -0
  258. aso-0.2.0/src/aso/context.py +67 -0
  259. aso-0.2.0/src/aso/database/__init__.py +45 -0
  260. aso-0.2.0/src/aso/database/builder.py +678 -0
  261. aso-0.2.0/src/aso/database/db.py +110 -0
  262. aso-0.2.0/src/aso/database/engine.py +217 -0
  263. aso-0.2.0/src/aso/database/factory.py +196 -0
  264. aso-0.2.0/src/aso/database/middleware.py +19 -0
  265. aso-0.2.0/src/aso/database/model.py +560 -0
  266. aso-0.2.0/src/aso/database/pagination.py +326 -0
  267. aso-0.2.0/src/aso/database/relationships.py +165 -0
  268. aso-0.2.0/src/aso/database/scope.py +174 -0
  269. aso-0.2.0/src/aso/database/seeder.py +67 -0
  270. aso-0.2.0/src/aso/database/types.py +160 -0
  271. aso-0.2.0/src/aso/events/__init__.py +24 -0
  272. aso-0.2.0/src/aso/events/event.py +128 -0
  273. aso-0.2.0/src/aso/events/listener_job.py +50 -0
  274. aso-0.2.0/src/aso/exceptions/__init__.py +45 -0
  275. aso-0.2.0/src/aso/exceptions/debug.py +104 -0
  276. aso-0.2.0/src/aso/exceptions/handler.py +366 -0
  277. aso-0.2.0/src/aso/exceptions/types.py +210 -0
  278. aso-0.2.0/src/aso/foundation/__init__.py +37 -0
  279. aso-0.2.0/src/aso/foundation/application.py +227 -0
  280. aso-0.2.0/src/aso/foundation/exceptions_config.py +49 -0
  281. aso-0.2.0/src/aso/foundation/middleware_config.py +141 -0
  282. aso-0.2.0/src/aso/foundation/paths.py +49 -0
  283. aso-0.2.0/src/aso/foundation/stack.py +165 -0
  284. aso-0.2.0/src/aso/http/__init__.py +36 -0
  285. aso-0.2.0/src/aso/http/controller.py +35 -0
  286. aso-0.2.0/src/aso/http/encoding.py +58 -0
  287. aso-0.2.0/src/aso/http/method_spoofing.py +72 -0
  288. aso-0.2.0/src/aso/http/middleware.py +149 -0
  289. aso-0.2.0/src/aso/http/request.py +284 -0
  290. aso-0.2.0/src/aso/http/responses.py +203 -0
  291. aso-0.2.0/src/aso/inertia/__init__.py +28 -0
  292. aso-0.2.0/src/aso/inertia/history.py +22 -0
  293. aso-0.2.0/src/aso/inertia/json_encode.py +45 -0
  294. aso-0.2.0/src/aso/inertia/middleware.py +108 -0
  295. aso-0.2.0/src/aso/inertia/property.py +23 -0
  296. aso-0.2.0/src/aso/inertia/props.py +150 -0
  297. aso-0.2.0/src/aso/inertia/response.py +390 -0
  298. aso-0.2.0/src/aso/inertia/root.py +40 -0
  299. aso-0.2.0/src/aso/inertia/shared.py +18 -0
  300. aso-0.2.0/src/aso/inertia/vite.py +150 -0
  301. aso-0.2.0/src/aso/log/__init__.py +10 -0
  302. aso-0.2.0/src/aso/log/manager.py +246 -0
  303. aso-0.2.0/src/aso/log/testing.py +59 -0
  304. aso-0.2.0/src/aso/mail/__init__.py +39 -0
  305. aso-0.2.0/src/aso/mail/drivers.py +138 -0
  306. aso-0.2.0/src/aso/mail/mailable.py +98 -0
  307. aso-0.2.0/src/aso/mail/manager.py +215 -0
  308. aso-0.2.0/src/aso/mail/queued_mail.py +24 -0
  309. aso-0.2.0/src/aso/mail/rendering.py +101 -0
  310. aso-0.2.0/src/aso/mail/resources/views/mail/layout.html +20 -0
  311. aso-0.2.0/src/aso/queue/__init__.py +39 -0
  312. aso-0.2.0/src/aso/queue/drivers.py +98 -0
  313. aso-0.2.0/src/aso/queue/failed.py +100 -0
  314. aso-0.2.0/src/aso/queue/job.py +90 -0
  315. aso-0.2.0/src/aso/queue/manager.py +257 -0
  316. aso-0.2.0/src/aso/queue/serialization.py +76 -0
  317. aso-0.2.0/src/aso/queue/worker.py +117 -0
  318. aso-0.2.0/src/aso/rate_limiting/__init__.py +20 -0
  319. aso-0.2.0/src/aso/rate_limiting/limit.py +40 -0
  320. aso-0.2.0/src/aso/rate_limiting/limiter.py +79 -0
  321. aso-0.2.0/src/aso/rate_limiting/middleware.py +73 -0
  322. aso-0.2.0/src/aso/routing/__init__.py +16 -0
  323. aso-0.2.0/src/aso/routing/paths.py +118 -0
  324. aso-0.2.0/src/aso/routing/pipeline.py +204 -0
  325. aso-0.2.0/src/aso/routing/registry.py +701 -0
  326. aso-0.2.0/src/aso/routing/signed.py +95 -0
  327. aso-0.2.0/src/aso/routing/static.py +42 -0
  328. aso-0.2.0/src/aso/routing/ts_routes.py +482 -0
  329. aso-0.2.0/src/aso/routing/url.py +65 -0
  330. aso-0.2.0/src/aso/security/__init__.py +9 -0
  331. aso-0.2.0/src/aso/security/crypt.py +57 -0
  332. aso-0.2.0/src/aso/security/hash.py +55 -0
  333. aso-0.2.0/src/aso/security/keys.py +66 -0
  334. aso-0.2.0/src/aso/session/__init__.py +40 -0
  335. aso-0.2.0/src/aso/session/configuration.py +54 -0
  336. aso-0.2.0/src/aso/session/drivers.py +239 -0
  337. aso-0.2.0/src/aso/session/forgery.py +157 -0
  338. aso-0.2.0/src/aso/session/middleware.py +161 -0
  339. aso-0.2.0/src/aso/session/store.py +255 -0
  340. aso-0.2.0/src/aso/storage/__init__.py +19 -0
  341. aso-0.2.0/src/aso/storage/manager.py +167 -0
  342. aso-0.2.0/src/aso/support/__init__.py +7 -0
  343. aso-0.2.0/src/aso/support/str_helpers.py +30 -0
  344. aso-0.2.0/src/aso/testing/__init__.py +31 -0
  345. aso-0.2.0/src/aso/testing/arch/__init__.py +12 -0
  346. aso-0.2.0/src/aso/testing/arch/_ast_utils.py +223 -0
  347. aso-0.2.0/src/aso/testing/arch/_preset.py +411 -0
  348. aso-0.2.0/src/aso/testing/arch/_selection.py +429 -0
  349. aso-0.2.0/src/aso/testing/client.py +305 -0
  350. aso-0.2.0/src/aso/testing/database.py +90 -0
  351. aso-0.2.0/src/aso/testing/inertia_assert.py +235 -0
  352. aso-0.2.0/src/aso/testing/options.py +27 -0
  353. aso-0.2.0/src/aso/testing/plugin.py +164 -0
  354. aso-0.2.0/src/aso/testing/response.py +358 -0
  355. aso-0.2.0/src/aso/validation/__init__.py +33 -0
  356. aso-0.2.0/src/aso/validation/form_request.py +259 -0
  357. aso-0.2.0/src/aso/validation/input.py +100 -0
  358. aso-0.2.0/src/aso/validation/messages.py +218 -0
  359. aso-0.2.0/src/aso/validation/rules.py +247 -0
  360. aso-0.2.0/src/aso/validation/uploaded_file.py +82 -0
  361. aso-0.2.0/tests/auth/conftest.py +92 -0
  362. aso-0.2.0/tests/auth/test_auth_app_stack.py +292 -0
  363. aso-0.2.0/tests/auth/test_events.py +56 -0
  364. aso-0.2.0/tests/auth/test_features.py +17 -0
  365. aso-0.2.0/tests/auth/test_gate.py +198 -0
  366. aso-0.2.0/tests/auth/test_guard_unit.py +129 -0
  367. aso-0.2.0/tests/auth/test_password_broker_unit.py +161 -0
  368. aso-0.2.0/tests/cache/conftest.py +14 -0
  369. aso-0.2.0/tests/cache/test_file_driver.py +100 -0
  370. aso-0.2.0/tests/cache/test_manager_unit.py +86 -0
  371. aso-0.2.0/tests/cache/test_memory_driver.py +135 -0
  372. aso-0.2.0/tests/cache/test_redis_driver.py +96 -0
  373. aso-0.2.0/tests/conftest.py +70 -0
  374. aso-0.2.0/tests/console/conftest.py +50 -0
  375. aso-0.2.0/tests/console/test_console_agents_update.py +64 -0
  376. aso-0.2.0/tests/console/test_console_cli.py +67 -0
  377. aso-0.2.0/tests/console/test_console_command.py +103 -0
  378. aso-0.2.0/tests/console/test_console_core_commands.py +136 -0
  379. aso-0.2.0/tests/console/test_console_doctor.py +43 -0
  380. aso-0.2.0/tests/console/test_console_handover.py +73 -0
  381. aso-0.2.0/tests/console/test_console_migrations.py +85 -0
  382. aso-0.2.0/tests/console/test_console_queue_commands.py +99 -0
  383. aso-0.2.0/tests/console/test_console_scheduler.py +145 -0
  384. aso-0.2.0/tests/console/test_console_seed_command.py +108 -0
  385. aso-0.2.0/tests/console/test_console_signature.py +83 -0
  386. aso-0.2.0/tests/console/test_console_user_commands.py +86 -0
  387. aso-0.2.0/tests/database/conftest.py +111 -0
  388. aso-0.2.0/tests/database/test_builder_bulk_chunk.py +64 -0
  389. aso-0.2.0/tests/database/test_builder_order_limit.py +144 -0
  390. aso-0.2.0/tests/database/test_builder_terminal.py +125 -0
  391. aso-0.2.0/tests/database/test_builder_where.py +169 -0
  392. aso-0.2.0/tests/database/test_db_raw.py +85 -0
  393. aso-0.2.0/tests/database/test_model_basics.py +365 -0
  394. aso-0.2.0/tests/database/test_model_crud.py +149 -0
  395. aso-0.2.0/tests/database/test_pagination.py +333 -0
  396. aso-0.2.0/tests/database/test_relationships.py +369 -0
  397. aso-0.2.0/tests/database/test_soft_deletes.py +85 -0
  398. aso-0.2.0/tests/database/test_transactions.py +266 -0
  399. aso-0.2.0/tests/database/test_types.py +69 -0
  400. aso-0.2.0/tests/database/test_uuids_ulids.py +54 -0
  401. aso-0.2.0/tests/e2e/README.md +14 -0
  402. aso-0.2.0/tests/e2e/browser.mjs +97 -0
  403. aso-0.2.0/tests/events/_event_fixtures.py +97 -0
  404. aso-0.2.0/tests/events/conftest.py +47 -0
  405. aso-0.2.0/tests/events/test_event_after_commit.py +53 -0
  406. aso-0.2.0/tests/events/test_event_dispatch.py +54 -0
  407. aso-0.2.0/tests/events/test_event_fake.py +70 -0
  408. aso-0.2.0/tests/events/test_order_shipment_stack.py +81 -0
  409. aso-0.2.0/tests/events/test_queued_listener.py +130 -0
  410. aso-0.2.0/tests/events/test_registry.py +53 -0
  411. aso-0.2.0/tests/exceptions/conftest.py +65 -0
  412. aso-0.2.0/tests/exceptions/test_builtin_conversions.py +134 -0
  413. aso-0.2.0/tests/exceptions/test_debug_page.py +25 -0
  414. aso-0.2.0/tests/exceptions/test_inertia_shared_data_fallback.py +43 -0
  415. aso-0.2.0/tests/exceptions/test_report_and_config.py +86 -0
  416. aso-0.2.0/tests/factories/conftest.py +69 -0
  417. aso-0.2.0/tests/factories/test_factory_core.py +169 -0
  418. aso-0.2.0/tests/factories/test_factory_relations.py +74 -0
  419. aso-0.2.0/tests/factories/test_seeder.py +81 -0
  420. aso-0.2.0/tests/fixtures/arch_bad/app/bootstrap_helpers.py +5 -0
  421. aso-0.2.0/tests/fixtures/arch_bad/app/config_leak.py +5 -0
  422. aso-0.2.0/tests/fixtures/arch_bad/app/http/controllers/post_controller.py +11 -0
  423. aso-0.2.0/tests/fixtures/arch_bad/app/http/controllers/profile_controller.py +9 -0
  424. aso-0.2.0/tests/fixtures/arch_bad/app/http/middleware/custom_middleware.py +7 -0
  425. aso-0.2.0/tests/fixtures/arch_bad/app/http/requests/profile_update_payload.py +7 -0
  426. aso-0.2.0/tests/fixtures/arch_bad/app/jobs/notify_job.py +13 -0
  427. aso-0.2.0/tests/fixtures/arch_bad/app/legacy_inertia.py +3 -0
  428. aso-0.2.0/tests/fixtures/arch_bad/app/models/comment.py +7 -0
  429. aso-0.2.0/tests/fixtures/arch_bad/app/models/post.py +10 -0
  430. aso-0.2.0/tests/fixtures/arch_bad/app/services/debug_helper.py +5 -0
  431. aso-0.2.0/tests/fixtures/arch_bad/app/services/search_service.py +8 -0
  432. aso-0.2.0/tests/fixtures/arch_bad/resources/js/pages/posts/index.tsx +3 -0
  433. aso-0.2.0/tests/fixtures/arch_bad/routes/web.py +7 -0
  434. aso-0.2.0/tests/fixtures/arch_good/app/http/controllers/post_controller.py +14 -0
  435. aso-0.2.0/tests/fixtures/arch_good/app/http/requests/store_post_request.py +7 -0
  436. aso-0.2.0/tests/fixtures/arch_good/app/jobs/send_welcome_email.py +11 -0
  437. aso-0.2.0/tests/fixtures/arch_good/app/models/post.py +9 -0
  438. aso-0.2.0/tests/fixtures/arch_good/resources/js/pages/posts/index.tsx +3 -0
  439. aso-0.2.0/tests/fixtures/arch_good/routes/web.py +12 -0
  440. aso-0.2.0/tests/fixtures/auth_app/app/__init__.py +0 -0
  441. aso-0.2.0/tests/fixtures/auth_app/app/http/__init__.py +0 -0
  442. aso-0.2.0/tests/fixtures/auth_app/app/http/controllers/__init__.py +0 -0
  443. aso-0.2.0/tests/fixtures/auth_app/app/http/controllers/confirm_password_controller.py +23 -0
  444. aso-0.2.0/tests/fixtures/auth_app/app/http/controllers/dashboard_controller.py +20 -0
  445. aso-0.2.0/tests/fixtures/auth_app/app/http/controllers/password_reset_controller.py +32 -0
  446. aso-0.2.0/tests/fixtures/auth_app/app/http/controllers/post_controller.py +13 -0
  447. aso-0.2.0/tests/fixtures/auth_app/app/http/controllers/registration_controller.py +29 -0
  448. aso-0.2.0/tests/fixtures/auth_app/app/http/controllers/session_controller.py +56 -0
  449. aso-0.2.0/tests/fixtures/auth_app/app/http/controllers/verification_controller.py +34 -0
  450. aso-0.2.0/tests/fixtures/auth_app/app/listeners/__init__.py +0 -0
  451. aso-0.2.0/tests/fixtures/auth_app/app/listeners/send_email_verification_notification.py +17 -0
  452. aso-0.2.0/tests/fixtures/auth_app/app/models/__init__.py +0 -0
  453. aso-0.2.0/tests/fixtures/auth_app/app/models/post.py +10 -0
  454. aso-0.2.0/tests/fixtures/auth_app/app/models/user.py +21 -0
  455. aso-0.2.0/tests/fixtures/auth_app/app/policies/__init__.py +0 -0
  456. aso-0.2.0/tests/fixtures/auth_app/app/policies/post_policy.py +12 -0
  457. aso-0.2.0/tests/fixtures/auth_app/bootstrap/app.py +15 -0
  458. aso-0.2.0/tests/fixtures/auth_app/config/app.py +7 -0
  459. aso-0.2.0/tests/fixtures/auth_app/config/auth.py +26 -0
  460. aso-0.2.0/tests/fixtures/auth_app/config/database.py +6 -0
  461. aso-0.2.0/tests/fixtures/auth_app/config/mail.py +14 -0
  462. aso-0.2.0/tests/fixtures/auth_app/config/session.py +4 -0
  463. aso-0.2.0/tests/fixtures/auth_app/routes/api.py +0 -0
  464. aso-0.2.0/tests/fixtures/auth_app/routes/web.py +43 -0
  465. aso-0.2.0/tests/fixtures/blog/app/__init__.py +0 -0
  466. aso-0.2.0/tests/fixtures/blog/app/http/__init__.py +0 -0
  467. aso-0.2.0/tests/fixtures/blog/app/http/controllers/__init__.py +0 -0
  468. aso-0.2.0/tests/fixtures/blog/app/http/controllers/post_controller.py +27 -0
  469. aso-0.2.0/tests/fixtures/blog/app/http/middleware/__init__.py +0 -0
  470. aso-0.2.0/tests/fixtures/blog/app/http/middleware/handle_inertia_requests.py +7 -0
  471. aso-0.2.0/tests/fixtures/blog/app/http/requests/__init__.py +0 -0
  472. aso-0.2.0/tests/fixtures/blog/app/http/requests/store_post_request.py +7 -0
  473. aso-0.2.0/tests/fixtures/blog/app/models/__init__.py +0 -0
  474. aso-0.2.0/tests/fixtures/blog/app/models/post.py +7 -0
  475. aso-0.2.0/tests/fixtures/blog/bootstrap/app.py +16 -0
  476. aso-0.2.0/tests/fixtures/blog/config/app.py +7 -0
  477. aso-0.2.0/tests/fixtures/blog/config/database.py +6 -0
  478. aso-0.2.0/tests/fixtures/blog/config/session.py +4 -0
  479. aso-0.2.0/tests/fixtures/blog/resources/js/pages/error.tsx +0 -0
  480. aso-0.2.0/tests/fixtures/blog/resources/js/pages/posts/create.tsx +0 -0
  481. aso-0.2.0/tests/fixtures/blog/resources/js/pages/posts/index.tsx +0 -0
  482. aso-0.2.0/tests/fixtures/blog/resources/views/app.html +3 -0
  483. aso-0.2.0/tests/fixtures/blog/routes/api.py +5 -0
  484. aso-0.2.0/tests/fixtures/blog/routes/web.py +9 -0
  485. aso-0.2.0/tests/fixtures/console_app/app/__init__.py +0 -0
  486. aso-0.2.0/tests/fixtures/console_app/app/console/__init__.py +0 -0
  487. aso-0.2.0/tests/fixtures/console_app/app/console/commands/__init__.py +0 -0
  488. aso-0.2.0/tests/fixtures/console_app/app/models/__init__.py +0 -0
  489. aso-0.2.0/tests/fixtures/console_app/app/models/post.py +10 -0
  490. aso-0.2.0/tests/fixtures/console_app/bootstrap/app.py +9 -0
  491. aso-0.2.0/tests/fixtures/console_app/config/app.py +7 -0
  492. aso-0.2.0/tests/fixtures/console_app/config/database.py +6 -0
  493. aso-0.2.0/tests/fixtures/console_app/config/session.py +2 -0
  494. aso-0.2.0/tests/fixtures/console_app/routes/web.py +8 -0
  495. aso-0.2.0/tests/fixtures/errors/app/__init__.py +0 -0
  496. aso-0.2.0/tests/fixtures/errors/app/exceptions/__init__.py +0 -0
  497. aso-0.2.0/tests/fixtures/errors/app/exceptions/app_error.py +11 -0
  498. aso-0.2.0/tests/fixtures/errors/app/exceptions/orders.py +19 -0
  499. aso-0.2.0/tests/fixtures/errors/app/exceptions/payment_declined.py +19 -0
  500. aso-0.2.0/tests/fixtures/errors/app/http/__init__.py +0 -0
  501. aso-0.2.0/tests/fixtures/errors/app/http/controllers/__init__.py +0 -0
  502. aso-0.2.0/tests/fixtures/errors/app/http/controllers/error_controller.py +57 -0
  503. aso-0.2.0/tests/fixtures/errors/app/http/middleware/__init__.py +0 -0
  504. aso-0.2.0/tests/fixtures/errors/app/http/middleware/crash_before_inertia.py +20 -0
  505. aso-0.2.0/tests/fixtures/errors/app/http/middleware/handle_inertia_requests.py +7 -0
  506. aso-0.2.0/tests/fixtures/errors/app/http/requests/__init__.py +0 -0
  507. aso-0.2.0/tests/fixtures/errors/app/http/requests/store_thing_request.py +8 -0
  508. aso-0.2.0/tests/fixtures/errors/bootstrap/app.py +46 -0
  509. aso-0.2.0/tests/fixtures/errors/config/app.py +7 -0
  510. aso-0.2.0/tests/fixtures/errors/config/session.py +4 -0
  511. aso-0.2.0/tests/fixtures/errors/resources/js/pages/error.tsx +0 -0
  512. aso-0.2.0/tests/fixtures/errors/resources/views/app.html +3 -0
  513. aso-0.2.0/tests/fixtures/errors/routes/api.py +9 -0
  514. aso-0.2.0/tests/fixtures/errors/routes/web.py +21 -0
  515. aso-0.2.0/tests/fixtures/factories_app/app/__init__.py +0 -0
  516. aso-0.2.0/tests/fixtures/factories_app/app/models/__init__.py +0 -0
  517. aso-0.2.0/tests/fixtures/factories_app/app/models/post.py +13 -0
  518. aso-0.2.0/tests/fixtures/factories_app/app/models/user.py +16 -0
  519. aso-0.2.0/tests/fixtures/factories_app/database/__init__.py +0 -0
  520. aso-0.2.0/tests/fixtures/factories_app/database/factories/__init__.py +0 -0
  521. aso-0.2.0/tests/fixtures/factories_app/database/factories/post_factory.py +13 -0
  522. aso-0.2.0/tests/fixtures/factories_app/database/factories/user_factory.py +20 -0
  523. aso-0.2.0/tests/fixtures/inertia_app/app/__init__.py +0 -0
  524. aso-0.2.0/tests/fixtures/inertia_app/app/http/__init__.py +0 -0
  525. aso-0.2.0/tests/fixtures/inertia_app/app/http/controllers/__init__.py +0 -0
  526. aso-0.2.0/tests/fixtures/inertia_app/app/http/controllers/errors_controller.py +16 -0
  527. aso-0.2.0/tests/fixtures/inertia_app/app/http/controllers/page_controller.py +66 -0
  528. aso-0.2.0/tests/fixtures/inertia_app/app/http/middleware/__init__.py +0 -0
  529. aso-0.2.0/tests/fixtures/inertia_app/app/http/middleware/handle_inertia_requests.py +17 -0
  530. aso-0.2.0/tests/fixtures/inertia_app/app/http/middleware/share_feature_flag.py +10 -0
  531. aso-0.2.0/tests/fixtures/inertia_app/app/http/requests/__init__.py +0 -0
  532. aso-0.2.0/tests/fixtures/inertia_app/app/http/requests/invite_member_request.py +8 -0
  533. aso-0.2.0/tests/fixtures/inertia_app/app/http/requests/store_thing_request.py +7 -0
  534. aso-0.2.0/tests/fixtures/inertia_app/bootstrap/app.py +17 -0
  535. aso-0.2.0/tests/fixtures/inertia_app/config/app.py +7 -0
  536. aso-0.2.0/tests/fixtures/inertia_app/config/session.py +4 -0
  537. aso-0.2.0/tests/fixtures/inertia_app/resources/js/pages/error.tsx +0 -0
  538. aso-0.2.0/tests/fixtures/inertia_app/resources/js/pages/errors/create.tsx +0 -0
  539. aso-0.2.0/tests/fixtures/inertia_app/resources/js/pages/kitchen.tsx +0 -0
  540. aso-0.2.0/tests/fixtures/inertia_app/resources/js/pages/shared.tsx +0 -0
  541. aso-0.2.0/tests/fixtures/inertia_app/resources/views/app.html +12 -0
  542. aso-0.2.0/tests/fixtures/inertia_app/routes/web.py +17 -0
  543. aso-0.2.0/tests/fixtures/orders_app/app/__init__.py +0 -0
  544. aso-0.2.0/tests/fixtures/orders_app/app/events/__init__.py +0 -0
  545. aso-0.2.0/tests/fixtures/orders_app/app/events/order_shipped.py +6 -0
  546. aso-0.2.0/tests/fixtures/orders_app/app/http/__init__.py +0 -0
  547. aso-0.2.0/tests/fixtures/orders_app/app/http/controllers/__init__.py +0 -0
  548. aso-0.2.0/tests/fixtures/orders_app/app/http/controllers/order_shipment_controller.py +42 -0
  549. aso-0.2.0/tests/fixtures/orders_app/app/listeners/__init__.py +0 -0
  550. aso-0.2.0/tests/fixtures/orders_app/app/listeners/log_shipment.py +14 -0
  551. aso-0.2.0/tests/fixtures/orders_app/app/listeners/send_shipment_notification.py +27 -0
  552. aso-0.2.0/tests/fixtures/orders_app/app/mail/__init__.py +0 -0
  553. aso-0.2.0/tests/fixtures/orders_app/app/mail/shipment_confirmation.py +14 -0
  554. aso-0.2.0/tests/fixtures/orders_app/app/models/__init__.py +0 -0
  555. aso-0.2.0/tests/fixtures/orders_app/app/models/order.py +8 -0
  556. aso-0.2.0/tests/fixtures/orders_app/bootstrap/app.py +17 -0
  557. aso-0.2.0/tests/fixtures/orders_app/config/app.py +7 -0
  558. aso-0.2.0/tests/fixtures/orders_app/config/database.py +6 -0
  559. aso-0.2.0/tests/fixtures/orders_app/config/mail.py +14 -0
  560. aso-0.2.0/tests/fixtures/orders_app/config/session.py +4 -0
  561. aso-0.2.0/tests/fixtures/orders_app/resources/views/mail/shipment_confirmation.html +6 -0
  562. aso-0.2.0/tests/fixtures/orders_app/routes/api.py +10 -0
  563. aso-0.2.0/tests/fixtures/orders_app/routes/web.py +0 -0
  564. aso-0.2.0/tests/fixtures/plugin_project/app/__init__.py +0 -0
  565. aso-0.2.0/tests/fixtures/plugin_project/app/http/__init__.py +0 -0
  566. aso-0.2.0/tests/fixtures/plugin_project/app/http/controllers/__init__.py +0 -0
  567. aso-0.2.0/tests/fixtures/plugin_project/app/http/controllers/post_controller.py +23 -0
  568. aso-0.2.0/tests/fixtures/plugin_project/app/http/middleware/__init__.py +0 -0
  569. aso-0.2.0/tests/fixtures/plugin_project/app/http/middleware/handle_inertia_requests.py +7 -0
  570. aso-0.2.0/tests/fixtures/plugin_project/app/models/__init__.py +0 -0
  571. aso-0.2.0/tests/fixtures/plugin_project/app/models/post.py +11 -0
  572. aso-0.2.0/tests/fixtures/plugin_project/app/models/user.py +15 -0
  573. aso-0.2.0/tests/fixtures/plugin_project/bootstrap/app.py +16 -0
  574. aso-0.2.0/tests/fixtures/plugin_project/checks_feature.py +43 -0
  575. aso-0.2.0/tests/fixtures/plugin_project/config/app.py +7 -0
  576. aso-0.2.0/tests/fixtures/plugin_project/config/auth.py +9 -0
  577. aso-0.2.0/tests/fixtures/plugin_project/config/database.py +6 -0
  578. aso-0.2.0/tests/fixtures/plugin_project/config/session.py +4 -0
  579. aso-0.2.0/tests/fixtures/plugin_project/pytest.ini +6 -0
  580. aso-0.2.0/tests/fixtures/plugin_project/resources/js/pages/posts/index.tsx +3 -0
  581. aso-0.2.0/tests/fixtures/plugin_project/resources/views/app.html +3 -0
  582. aso-0.2.0/tests/fixtures/plugin_project/routes/web.py +6 -0
  583. aso-0.2.0/tests/fixtures/routing_app/app/__init__.py +0 -0
  584. aso-0.2.0/tests/fixtures/routing_app/app/http/__init__.py +0 -0
  585. aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/__init__.py +0 -0
  586. aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/comment_controller.py +34 -0
  587. aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/convert_controller.py +49 -0
  588. aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/fallback_controller.py +7 -0
  589. aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/gated_controller.py +15 -0
  590. aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/group_controller.py +20 -0
  591. aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/misc_controller.py +190 -0
  592. aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/ping_invokable.py +8 -0
  593. aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/post_controller.py +36 -0
  594. aso-0.2.0/tests/fixtures/routing_app/app/http/controllers/stub_controllers.py +40 -0
  595. aso-0.2.0/tests/fixtures/routing_app/app/http/middleware/__init__.py +0 -0
  596. aso-0.2.0/tests/fixtures/routing_app/app/http/middleware/bodypeek.py +15 -0
  597. aso-0.2.0/tests/fixtures/routing_app/app/http/middleware/handle_inertia_requests.py +7 -0
  598. aso-0.2.0/tests/fixtures/routing_app/app/http/middleware/header_mutator.py +12 -0
  599. aso-0.2.0/tests/fixtures/routing_app/app/http/middleware/raiser.py +11 -0
  600. aso-0.2.0/tests/fixtures/routing_app/app/http/middleware/recording.py +45 -0
  601. aso-0.2.0/tests/fixtures/routing_app/app/http/middleware/role.py +13 -0
  602. aso-0.2.0/tests/fixtures/routing_app/app/http/middleware/short_circuit.py +11 -0
  603. aso-0.2.0/tests/fixtures/routing_app/app/http/requests/__init__.py +0 -0
  604. aso-0.2.0/tests/fixtures/routing_app/app/http/requests/store_post_request.py +8 -0
  605. aso-0.2.0/tests/fixtures/routing_app/app/http/requests/update_post_request.py +7 -0
  606. aso-0.2.0/tests/fixtures/routing_app/app/models/__init__.py +0 -0
  607. aso-0.2.0/tests/fixtures/routing_app/app/models/comment.py +11 -0
  608. aso-0.2.0/tests/fixtures/routing_app/app/models/post.py +10 -0
  609. aso-0.2.0/tests/fixtures/routing_app/bootstrap/app.py +38 -0
  610. aso-0.2.0/tests/fixtures/routing_app/config/app.py +7 -0
  611. aso-0.2.0/tests/fixtures/routing_app/config/database.py +6 -0
  612. aso-0.2.0/tests/fixtures/routing_app/config/session.py +4 -0
  613. aso-0.2.0/tests/fixtures/routing_app/resources/js/pages/about.tsx +0 -0
  614. aso-0.2.0/tests/fixtures/routing_app/resources/views/app.html +3 -0
  615. aso-0.2.0/tests/fixtures/routing_app/routes/api.py +10 -0
  616. aso-0.2.0/tests/fixtures/routing_app/routes/included.py +7 -0
  617. aso-0.2.0/tests/fixtures/routing_app/routes/web.py +149 -0
  618. aso-0.2.0/tests/fixtures/session_app/bootstrap/app.py +20 -0
  619. aso-0.2.0/tests/fixtures/session_app/config/app.py +7 -0
  620. aso-0.2.0/tests/fixtures/session_app/config/session.py +12 -0
  621. aso-0.2.0/tests/fixtures/session_app/resources/js/pages/error.tsx +0 -0
  622. aso-0.2.0/tests/fixtures/session_app/resources/views/app.html +3 -0
  623. aso-0.2.0/tests/fixtures/session_app/routes/web.py +60 -0
  624. aso-0.2.0/tests/fixtures/testing_app/app/__init__.py +0 -0
  625. aso-0.2.0/tests/fixtures/testing_app/app/http/__init__.py +0 -0
  626. aso-0.2.0/tests/fixtures/testing_app/app/http/controllers/__init__.py +0 -0
  627. aso-0.2.0/tests/fixtures/testing_app/app/http/controllers/api_post_controller.py +19 -0
  628. aso-0.2.0/tests/fixtures/testing_app/app/http/controllers/post_controller.py +36 -0
  629. aso-0.2.0/tests/fixtures/testing_app/app/http/middleware/__init__.py +0 -0
  630. aso-0.2.0/tests/fixtures/testing_app/app/http/middleware/handle_inertia_requests.py +15 -0
  631. aso-0.2.0/tests/fixtures/testing_app/app/http/requests/__init__.py +0 -0
  632. aso-0.2.0/tests/fixtures/testing_app/app/http/requests/store_post_request.py +10 -0
  633. aso-0.2.0/tests/fixtures/testing_app/app/models/__init__.py +0 -0
  634. aso-0.2.0/tests/fixtures/testing_app/app/models/post.py +13 -0
  635. aso-0.2.0/tests/fixtures/testing_app/app/models/user.py +16 -0
  636. aso-0.2.0/tests/fixtures/testing_app/bootstrap/app.py +16 -0
  637. aso-0.2.0/tests/fixtures/testing_app/config/app.py +7 -0
  638. aso-0.2.0/tests/fixtures/testing_app/config/auth.py +9 -0
  639. aso-0.2.0/tests/fixtures/testing_app/config/database.py +6 -0
  640. aso-0.2.0/tests/fixtures/testing_app/config/session.py +4 -0
  641. aso-0.2.0/tests/fixtures/testing_app/resources/js/pages/error.tsx +3 -0
  642. aso-0.2.0/tests/fixtures/testing_app/resources/js/pages/posts/create.tsx +3 -0
  643. aso-0.2.0/tests/fixtures/testing_app/resources/js/pages/posts/index.tsx +3 -0
  644. aso-0.2.0/tests/fixtures/testing_app/resources/js/pages/posts/show.tsx +3 -0
  645. aso-0.2.0/tests/fixtures/testing_app/resources/views/app.html +3 -0
  646. aso-0.2.0/tests/fixtures/testing_app/routes/api.py +7 -0
  647. aso-0.2.0/tests/fixtures/testing_app/routes/web.py +9 -0
  648. aso-0.2.0/tests/fixtures/throttle_app/app/__init__.py +0 -0
  649. aso-0.2.0/tests/fixtures/throttle_app/app/http/__init__.py +0 -0
  650. aso-0.2.0/tests/fixtures/throttle_app/app/http/controllers/__init__.py +0 -0
  651. aso-0.2.0/tests/fixtures/throttle_app/app/http/controllers/ping_controller.py +14 -0
  652. aso-0.2.0/tests/fixtures/throttle_app/app/http/middleware/__init__.py +0 -0
  653. aso-0.2.0/tests/fixtures/throttle_app/bootstrap/app.py +16 -0
  654. aso-0.2.0/tests/fixtures/throttle_app/config/app.py +7 -0
  655. aso-0.2.0/tests/fixtures/throttle_app/config/database.py +6 -0
  656. aso-0.2.0/tests/fixtures/throttle_app/config/session.py +4 -0
  657. aso-0.2.0/tests/fixtures/throttle_app/routes/api.py +5 -0
  658. aso-0.2.0/tests/fixtures/throttle_app/routes/web.py +7 -0
  659. aso-0.2.0/tests/fixtures/validation_app/app/__init__.py +0 -0
  660. aso-0.2.0/tests/fixtures/validation_app/app/http/__init__.py +0 -0
  661. aso-0.2.0/tests/fixtures/validation_app/app/http/controllers/__init__.py +0 -0
  662. aso-0.2.0/tests/fixtures/validation_app/app/http/controllers/debug_controller.py +13 -0
  663. aso-0.2.0/tests/fixtures/validation_app/app/http/controllers/form_controller.py +77 -0
  664. aso-0.2.0/tests/fixtures/validation_app/app/http/middleware/__init__.py +0 -0
  665. aso-0.2.0/tests/fixtures/validation_app/app/http/middleware/handle_inertia_requests.py +7 -0
  666. aso-0.2.0/tests/fixtures/validation_app/app/http/requests/__init__.py +0 -0
  667. aso-0.2.0/tests/fixtures/validation_app/app/http/requests/order_request.py +13 -0
  668. aso-0.2.0/tests/fixtures/validation_app/app/http/requests/profile_requests.py +50 -0
  669. aso-0.2.0/tests/fixtures/validation_app/app/http/requests/store_post_request.py +47 -0
  670. aso-0.2.0/tests/fixtures/validation_app/app/models/__init__.py +0 -0
  671. aso-0.2.0/tests/fixtures/validation_app/app/models/team.py +9 -0
  672. aso-0.2.0/tests/fixtures/validation_app/app/models/user.py +10 -0
  673. aso-0.2.0/tests/fixtures/validation_app/bootstrap/app.py +16 -0
  674. aso-0.2.0/tests/fixtures/validation_app/config/app.py +7 -0
  675. aso-0.2.0/tests/fixtures/validation_app/config/database.py +6 -0
  676. aso-0.2.0/tests/fixtures/validation_app/config/session.py +4 -0
  677. aso-0.2.0/tests/fixtures/validation_app/resources/js/pages/error.tsx +0 -0
  678. aso-0.2.0/tests/fixtures/validation_app/resources/js/pages/forms/create.tsx +0 -0
  679. aso-0.2.0/tests/fixtures/validation_app/resources/views/app.html +3 -0
  680. aso-0.2.0/tests/fixtures/validation_app/routes/api.py +6 -0
  681. aso-0.2.0/tests/fixtures/validation_app/routes/web.py +22 -0
  682. aso-0.2.0/tests/generators/conftest.py +99 -0
  683. aso-0.2.0/tests/generators/test_make_controller.py +80 -0
  684. aso-0.2.0/tests/generators/test_make_misc.py +167 -0
  685. aso-0.2.0/tests/generators/test_make_model.py +131 -0
  686. aso-0.2.0/tests/generators/test_overwrite_guard.py +56 -0
  687. aso-0.2.0/tests/generators/test_stub_publish.py +56 -0
  688. aso-0.2.0/tests/http/conftest.py +73 -0
  689. aso-0.2.0/tests/http/test_controller.py +41 -0
  690. aso-0.2.0/tests/http/test_encoding_unit.py +64 -0
  691. aso-0.2.0/tests/http/test_method_spoofing.py +44 -0
  692. aso-0.2.0/tests/http/test_middleware_adapter.py +52 -0
  693. aso-0.2.0/tests/http/test_request_api.py +108 -0
  694. aso-0.2.0/tests/http/test_response_builder.py +56 -0
  695. aso-0.2.0/tests/http/test_responses.py +152 -0
  696. aso-0.2.0/tests/http/test_return_value_conversion.py +50 -0
  697. aso-0.2.0/tests/inertia/conftest.py +56 -0
  698. aso-0.2.0/tests/inertia/test_errors_and_flash.py +82 -0
  699. aso-0.2.0/tests/inertia/test_history_and_location.py +43 -0
  700. aso-0.2.0/tests/inertia/test_json_encode.py +65 -0
  701. aso-0.2.0/tests/inertia/test_prop_categories.py +154 -0
  702. aso-0.2.0/tests/inertia/test_props_unit.py +103 -0
  703. aso-0.2.0/tests/inertia/test_shared_and_version.py +64 -0
  704. aso-0.2.0/tests/inertia/test_vite.py +149 -0
  705. aso-0.2.0/tests/inertia/test_vite_helpers_build_css.py +22 -0
  706. aso-0.2.0/tests/log/test_capture_and_configure.py +69 -0
  707. aso-0.2.0/tests/log/test_channels.py +99 -0
  708. aso-0.2.0/tests/log/test_context_and_redaction.py +66 -0
  709. aso-0.2.0/tests/log/test_log_facade.py +65 -0
  710. aso-0.2.0/tests/mail/conftest.py +37 -0
  711. aso-0.2.0/tests/mail/test_mail_after_commit.py +55 -0
  712. aso-0.2.0/tests/mail/test_mail_drivers.py +192 -0
  713. aso-0.2.0/tests/mail/test_mail_fake.py +110 -0
  714. aso-0.2.0/tests/mail/test_mailable.py +160 -0
  715. aso-0.2.0/tests/mail/test_pending_mail.py +243 -0
  716. aso-0.2.0/tests/mail/test_rendering.py +38 -0
  717. aso-0.2.0/tests/queue/_jobs.py +104 -0
  718. aso-0.2.0/tests/queue/conftest.py +51 -0
  719. aso-0.2.0/tests/queue/test_after_commit.py +45 -0
  720. aso-0.2.0/tests/queue/test_after_response.py +37 -0
  721. aso-0.2.0/tests/queue/test_dispatch.py +62 -0
  722. aso-0.2.0/tests/queue/test_drivers_config.py +51 -0
  723. aso-0.2.0/tests/queue/test_failed_jobs.py +52 -0
  724. aso-0.2.0/tests/queue/test_fake.py +60 -0
  725. aso-0.2.0/tests/queue/test_retries_and_worker.py +82 -0
  726. aso-0.2.0/tests/queue/test_serialization.py +48 -0
  727. aso-0.2.0/tests/queue/test_worker_restart.py +30 -0
  728. aso-0.2.0/tests/rate_limiting/conftest.py +52 -0
  729. aso-0.2.0/tests/rate_limiting/test_limiter_unit.py +54 -0
  730. aso-0.2.0/tests/rate_limiting/test_throttle_feature.py +77 -0
  731. aso-0.2.0/tests/routing/conftest.py +73 -0
  732. aso-0.2.0/tests/routing/test_feature_middleware.py +99 -0
  733. aso-0.2.0/tests/routing/test_feature_resources_and_binding.py +147 -0
  734. aso-0.2.0/tests/routing/test_feature_signed_and_misc.py +100 -0
  735. aso-0.2.0/tests/routing/test_feature_verbs_and_groups.py +107 -0
  736. aso-0.2.0/tests/routing/test_paths_unit.py +85 -0
  737. aso-0.2.0/tests/routing/test_pipeline_unit.py +143 -0
  738. aso-0.2.0/tests/routing/test_public_files.py +26 -0
  739. aso-0.2.0/tests/routing/test_registry_unit.py +275 -0
  740. aso-0.2.0/tests/security/test_crypt.py +64 -0
  741. aso-0.2.0/tests/security/test_hash.py +38 -0
  742. aso-0.2.0/tests/security/test_keys.py +50 -0
  743. aso-0.2.0/tests/session/test_drivers.py +227 -0
  744. aso-0.2.0/tests/session/test_middleware_integration.py +168 -0
  745. aso-0.2.0/tests/session/test_store.py +233 -0
  746. aso-0.2.0/tests/skeleton/test_new_command.py +70 -0
  747. aso-0.2.0/tests/storage/conftest.py +14 -0
  748. aso-0.2.0/tests/storage/test_disk_unit.py +104 -0
  749. aso-0.2.0/tests/storage/test_storage_link.py +60 -0
  750. aso-0.2.0/tests/storage/test_uploaded_file_store.py +59 -0
  751. aso-0.2.0/tests/support/test_slug.py +33 -0
  752. aso-0.2.0/tests/test_spine_loop.py +124 -0
  753. aso-0.2.0/tests/testing/conftest.py +87 -0
  754. aso-0.2.0/tests/testing/test_arch_rules.py +162 -0
  755. aso-0.2.0/tests/testing/test_client_assertions.py +82 -0
  756. aso-0.2.0/tests/testing/test_client_requests.py +123 -0
  757. aso-0.2.0/tests/testing/test_database_assertions.py +52 -0
  758. aso-0.2.0/tests/testing/test_inertia_assert_unit.py +75 -0
  759. aso-0.2.0/tests/testing/test_inertia_assertions.py +123 -0
  760. aso-0.2.0/tests/testing/test_plugin_end_to_end.py +50 -0
  761. aso-0.2.0/tests/testing/test_test_command.py +52 -0
  762. aso-0.2.0/tests/ts_routes/conftest.py +37 -0
  763. aso-0.2.0/tests/ts_routes/test_generator.py +139 -0
  764. aso-0.2.0/tests/validation/conftest.py +58 -0
  765. aso-0.2.0/tests/validation/test_input.py +55 -0
  766. aso-0.2.0/tests/validation/test_integration.py +269 -0
  767. aso-0.2.0/tests/validation/test_messages.py +133 -0
  768. aso-0.2.0/tests/validation/test_rules_unit.py +115 -0
  769. aso-0.2.0/tests/validation/test_uploaded_file.py +58 -0
  770. 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
@@ -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
@@ -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("/")