fastapi-startkit 0.63.0__tar.gz → 0.65.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 (365) hide show
  1. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/PKG-INFO +14 -1
  2. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/README.md +10 -0
  3. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/pyproject.toml +5 -2
  4. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/fastapi/exceptions.py +15 -0
  5. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/inertia/session.py +4 -1
  6. fastapi_startkit-0.65.0/src/fastapi_startkit/inertia/testing.py +140 -0
  7. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/collection/Collection.py +8 -9
  8. fastapi_startkit-0.65.0/src/fastapi_startkit/masoniteorm/exceptions.py +22 -0
  9. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/models/caster.py +2 -1
  10. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/models/model.py +4 -0
  11. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/query/EagerLoadMixin.py +6 -10
  12. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/relationships/BaseRelationship.py +66 -8
  13. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/relationships/BelongsTo.py +4 -6
  14. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/relationships/BelongsToMany.py +4 -5
  15. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/relationships/HasMany.py +3 -3
  16. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/relationships/HasManyThrough.py +8 -11
  17. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/relationships/HasOne.py +4 -5
  18. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/relationships/HasOneThrough.py +5 -8
  19. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/relationships/MorphMany.py +5 -4
  20. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/relationships/MorphOne.py +5 -4
  21. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/relationships/MorphTo.py +5 -4
  22. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/relationships/MorphToMany.py +8 -4
  23. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/skills/stubs/.ai/fastapi-startkit/database/SKILL.md +36 -4
  24. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/support/collection.py +3 -1
  25. fastapi_startkit-0.63.0/src/fastapi_startkit/inertia/testing.py +0 -14
  26. fastapi_startkit-0.63.0/src/fastapi_startkit/masoniteorm/exceptions.py +0 -12
  27. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/.DS_Store +0 -0
  28. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/__init__.py +0 -0
  29. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/__init__.py +0 -0
  30. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/agent.py +0 -0
  31. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/ai.py +0 -0
  32. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/audio.py +0 -0
  33. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/audio_factory.py +0 -0
  34. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/config/ai.py +0 -0
  35. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/config/config.py +0 -0
  36. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/decorators.py +0 -0
  37. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/document.py +0 -0
  38. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/image.py +0 -0
  39. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/image_factory.py +0 -0
  40. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/judge.py +0 -0
  41. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/lab.py +0 -0
  42. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/pipeline.py +0 -0
  43. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/providers/__init__.py +0 -0
  44. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/providers/ai_provider.py +0 -0
  45. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/recording.py +0 -0
  46. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/runner.py +0 -0
  47. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/state.py +0 -0
  48. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/testing.py +0 -0
  49. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/tinker.py +0 -0
  50. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/ai/types.py +0 -0
  51. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/application.py +0 -0
  52. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/broadcasting/__init__.py +0 -0
  53. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/broadcasting/auth.py +0 -0
  54. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/broadcasting/channels.py +0 -0
  55. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/broadcasting/config.py +0 -0
  56. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/broadcasting/drivers/__init__.py +0 -0
  57. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/broadcasting/drivers/log_driver.py +0 -0
  58. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/broadcasting/drivers/reverb_driver.py +0 -0
  59. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/broadcasting/event.py +0 -0
  60. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/broadcasting/helpers.py +0 -0
  61. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/broadcasting/manager.py +0 -0
  62. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/broadcasting/provider.py +0 -0
  63. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/broadcasting/reverb/__init__.py +0 -0
  64. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/broadcasting/reverb/channel_manager.py +0 -0
  65. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/broadcasting/reverb/connection.py +0 -0
  66. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/broadcasting/reverb/server.py +0 -0
  67. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/broadcasting/stubs/__init__.py +0 -0
  68. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/broadcasting/stubs/channels.py +0 -0
  69. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/carbon/__init__.py +0 -0
  70. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/carbon/carbon.py +0 -0
  71. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/config/__init__.py +0 -0
  72. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/config/app.py +0 -0
  73. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/configuration/Configuration.py +0 -0
  74. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/configuration/__init__.py +0 -0
  75. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/configuration/config.py +0 -0
  76. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/configuration/helpers.py +0 -0
  77. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/configuration/providers/ConfigurationProvider.py +0 -0
  78. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/configuration/providers/__init__.py +0 -0
  79. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/console/__init__.py +0 -0
  80. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/console/application.py +0 -0
  81. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/console/can_override_config.py +0 -0
  82. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/console/can_override_default_options.py +0 -0
  83. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/console/command.py +0 -0
  84. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/console/publish_command.py +0 -0
  85. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/container/__init__.py +0 -0
  86. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/container/container.py +0 -0
  87. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/environment/__init__.py +0 -0
  88. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/environment/environment.py +0 -0
  89. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/events/__init__.py +0 -0
  90. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/events/dispatcher.py +0 -0
  91. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/events/fake.py +0 -0
  92. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/events/helpers.py +0 -0
  93. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/events/listener.py +0 -0
  94. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/events/provider.py +0 -0
  95. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/exceptions/__init__.py +0 -0
  96. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/exceptions/exceptions.py +0 -0
  97. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/exceptions/handler.py +0 -0
  98. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/AI.py +0 -0
  99. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/AI.pyi +0 -0
  100. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Cache.py +0 -0
  101. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Config.py +0 -0
  102. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Config.pyi +0 -0
  103. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Dump.py +0 -0
  104. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Dump.pyi +0 -0
  105. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Event.py +0 -0
  106. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Event.pyi +0 -0
  107. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Facade.py +0 -0
  108. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Gate.py +0 -0
  109. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Gate.pyi +0 -0
  110. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Hash.py +0 -0
  111. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Hash.pyi +0 -0
  112. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Loader.py +0 -0
  113. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Loader.pyi +0 -0
  114. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Mail.py +0 -0
  115. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Mail.pyi +0 -0
  116. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Notification.py +0 -0
  117. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Notification.pyi +0 -0
  118. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Queue.py +0 -0
  119. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Queue.pyi +0 -0
  120. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/RateLimiter.py +0 -0
  121. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/RateLimiter.pyi +0 -0
  122. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Redis.py +0 -0
  123. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Redis.pyi +0 -0
  124. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Request.py +0 -0
  125. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Request.pyi +0 -0
  126. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Response.py +0 -0
  127. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Response.pyi +0 -0
  128. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Session.py +0 -0
  129. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Session.pyi +0 -0
  130. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Url.py +0 -0
  131. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Url.pyi +0 -0
  132. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/View.py +0 -0
  133. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/View.pyi +0 -0
  134. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Vite.py +0 -0
  135. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/Vite.pyi +0 -0
  136. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/facades/__init__.py +0 -0
  137. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/fastapi/__init__.py +0 -0
  138. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/fastapi/commands/__init__.py +0 -0
  139. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/fastapi/commands/serve_command.py +0 -0
  140. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/fastapi/config/__init__.py +0 -0
  141. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/fastapi/config/fastapi.py +0 -0
  142. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/fastapi/events.py +0 -0
  143. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/fastapi/middleware.py +0 -0
  144. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/fastapi/providers/fastapi_provider.py +0 -0
  145. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/fastapi/referer.py +0 -0
  146. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/fastapi/requests/model.py +0 -0
  147. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/fastapi/routers/router.py +0 -0
  148. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/fastapi/testing/__init__.py +0 -0
  149. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/fastapi/testing/assertable_json.py +0 -0
  150. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/fastapi/testing/test_case.py +0 -0
  151. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/fastapi/testing/test_response.py +0 -0
  152. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/foundation/app_provider.py +0 -0
  153. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/inertia/__init__.py +0 -0
  154. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/inertia/constant.py +0 -0
  155. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/inertia/context.py +0 -0
  156. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/inertia/encoding.py +0 -0
  157. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/inertia/errors.py +0 -0
  158. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/inertia/inertia.py +0 -0
  159. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/inertia/middleware.py +0 -0
  160. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/inertia/props/props.py +0 -0
  161. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/inertia/props/resolver.py +0 -0
  162. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/inertia/props/scroll.py +0 -0
  163. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/inertia/provider.py +0 -0
  164. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/inertia/redirect.py +0 -0
  165. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/inertia/ssr.py +0 -0
  166. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/jsonapi/__init__.py +0 -0
  167. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/jsonapi/response.py +0 -0
  168. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/loader/Loader.py +0 -0
  169. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/loader/__init__.py +0 -0
  170. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/ChannelFactory.py +0 -0
  171. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/__init__.py +0 -0
  172. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/channels/BaseChannel.py +0 -0
  173. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/channels/DailyChannel.py +0 -0
  174. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/channels/MultiBaseChannel.py +0 -0
  175. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/channels/SingleChannel.py +0 -0
  176. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/channels/SlackChannel.py +0 -0
  177. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/channels/StackChannel.py +0 -0
  178. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/channels/SyslogChannel.py +0 -0
  179. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/channels/TerminalChannel.py +0 -0
  180. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/channels/__init__.py +0 -0
  181. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/config/__init__.py +0 -0
  182. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/config/channels.py +0 -0
  183. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/config/logging.py +0 -0
  184. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/drivers/BaseDriver.py +0 -0
  185. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/drivers/LogSingleDriver.py +0 -0
  186. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/drivers/LogSlackDriver.py +0 -0
  187. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/drivers/LogSyslogDriver.py +0 -0
  188. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/drivers/LogTerminalDriver.py +0 -0
  189. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/drivers/__init__.py +0 -0
  190. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/factory.py +0 -0
  191. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/file.py +0 -0
  192. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/handler.py +0 -0
  193. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/listeners.py +0 -0
  194. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/logger.py +0 -0
  195. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/managers/LoggingManager.py +0 -0
  196. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/managers/__init__.py +0 -0
  197. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/providers/__init__.py +0 -0
  198. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/logging/providers/log_provider.py +0 -0
  199. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/__init__.py +0 -0
  200. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/collection/__init__.py +0 -0
  201. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/DBMigrateCommand.py +0 -0
  202. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/DBSeedCommand.py +0 -0
  203. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/MakeMigrationCommand.py +0 -0
  204. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/MakeModelCommand.py +0 -0
  205. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/MakeObserverCommand.py +0 -0
  206. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/MakeSeedCommand.py +0 -0
  207. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/MigrateFreshCommand.py +0 -0
  208. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/MigrateRefreshCommand.py +0 -0
  209. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/MigrateResetCommand.py +0 -0
  210. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/MigrateRollbackCommand.py +0 -0
  211. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/MigrateStatusCommand.py +0 -0
  212. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/ShellCommand.py +0 -0
  213. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/__init__.py +0 -0
  214. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/stubs/create_migration.stub +0 -0
  215. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/stubs/create_seed.stub +0 -0
  216. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/stubs/model.stub +0 -0
  217. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/stubs/observer.stub +0 -0
  218. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/commands/stubs/table_migration.stub +0 -0
  219. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/config/__init__.py +0 -0
  220. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/config/config.py +0 -0
  221. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/config/database.py +0 -0
  222. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/connections/connection.py +0 -0
  223. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/connections/factory.py +0 -0
  224. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/connections/manager.py +0 -0
  225. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/connections/manages_transactions.py +0 -0
  226. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/connections/mysql_connection.py +0 -0
  227. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/connections/postgres_connection.py +0 -0
  228. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/connections/sqlite_connection.py +0 -0
  229. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/connections/transactions.py +0 -0
  230. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/expressions/__init__.py +0 -0
  231. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/expressions/expressions.py +0 -0
  232. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/facades/DB.py +0 -0
  233. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/facades/Schema.py +0 -0
  234. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/facades/__init__.py +0 -0
  235. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/factory/__init__.py +0 -0
  236. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/factory/factory.py +0 -0
  237. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/helpers/__init__.py +0 -0
  238. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/helpers/misc.py +0 -0
  239. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/migrations/Migration.py +0 -0
  240. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/migrations/Migrator.py +0 -0
  241. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/migrations/__init__.py +0 -0
  242. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/models/MigrationModel.py +0 -0
  243. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/models/__init__.py +0 -0
  244. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/models/attribute.py +0 -0
  245. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/models/builder.py +0 -0
  246. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/models/fields.py +0 -0
  247. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/models/observer.py +0 -0
  248. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/models/pivot.py +0 -0
  249. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/models/registry.py +0 -0
  250. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/models/relationship.py +0 -0
  251. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/observers/ObservesEvents.py +0 -0
  252. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/observers/__init__.py +0 -0
  253. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/pagination/BasePaginator.py +0 -0
  254. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/pagination/LengthAwarePaginator.py +0 -0
  255. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/pagination/SimplePaginator.py +0 -0
  256. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/pagination/__init__.py +0 -0
  257. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/providers/DatabaseProvider.py +0 -0
  258. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/providers/__init__.py +0 -0
  259. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/query/EagerRelation.py +0 -0
  260. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/query/__init__.py +0 -0
  261. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/query/grammars/BaseGrammar.py +0 -0
  262. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/query/grammars/MSSQLGrammar.py +0 -0
  263. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/query/grammars/MySQLGrammar.py +0 -0
  264. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/query/grammars/PostgresGrammar.py +0 -0
  265. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/query/grammars/SQLiteGrammar.py +0 -0
  266. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/query/grammars/__init__.py +0 -0
  267. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/query/processors/MSSQLPostProcessor.py +0 -0
  268. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/query/processors/MySQLPostProcessor.py +0 -0
  269. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/query/processors/PostgresPostProcessor.py +0 -0
  270. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/query/processors/SQLitePostProcessor.py +0 -0
  271. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/query/processors/__init__.py +0 -0
  272. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/query/support.py +0 -0
  273. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/relationships/__init__.py +0 -0
  274. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/schema/Blueprint.py +0 -0
  275. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/schema/Column.py +0 -0
  276. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/schema/ColumnDiff.py +0 -0
  277. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/schema/Constraint.py +0 -0
  278. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/schema/ForeignKeyConstraint.py +0 -0
  279. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/schema/Index.py +0 -0
  280. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/schema/Table.py +0 -0
  281. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/schema/TableDiff.py +0 -0
  282. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/schema/__init__.py +0 -0
  283. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/schema/platforms/MSSQLPlatform.py +0 -0
  284. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/schema/platforms/MySQLPlatform.py +0 -0
  285. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/schema/platforms/Platform.py +0 -0
  286. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/schema/platforms/PostgresPlatform.py +0 -0
  287. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/schema/platforms/SQLitePlatform.py +0 -0
  288. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/schema/platforms/__init__.py +0 -0
  289. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/schema/schema.py +0 -0
  290. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/seeders/Seeder.py +0 -0
  291. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/seeders/__init__.py +0 -0
  292. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/stubs/create-migration.html +0 -0
  293. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/stubs/table-migration.html +0 -0
  294. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/testing/__init__.py +0 -0
  295. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/masoniteorm/testing/transaction.py +0 -0
  296. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/mcp/__init__.py +0 -0
  297. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/mcp/argument.py +0 -0
  298. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/mcp/prompt.py +0 -0
  299. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/mcp/protocol.py +0 -0
  300. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/mcp/providers/__init__.py +0 -0
  301. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/mcp/providers/mcp_provider.py +0 -0
  302. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/mcp/request.py +0 -0
  303. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/mcp/resource.py +0 -0
  304. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/mcp/response.py +0 -0
  305. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/mcp/server.py +0 -0
  306. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/mcp/tool.py +0 -0
  307. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/process/__init__.py +0 -0
  308. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/process/exception.py +0 -0
  309. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/process/fake.py +0 -0
  310. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/process/process.py +0 -0
  311. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/process/result.py +0 -0
  312. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/py.typed +0 -0
  313. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/redis/__init__.py +0 -0
  314. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/redis/config.py +0 -0
  315. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/redis/connection.py +0 -0
  316. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/redis/connector.py +0 -0
  317. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/redis/manager.py +0 -0
  318. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/redis/prefix.py +0 -0
  319. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/redis/provider.py +0 -0
  320. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/skills/__init__.py +0 -0
  321. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/skills/adapters/__init__.py +0 -0
  322. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/skills/adapters/base.py +0 -0
  323. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/skills/adapters/claude.py +0 -0
  324. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/skills/adapters/gemini.py +0 -0
  325. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/skills/commands/__init__.py +0 -0
  326. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/skills/commands/skills.py +0 -0
  327. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/skills/parser.py +0 -0
  328. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/skills/provider.py +0 -0
  329. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/skills/registry.py +0 -0
  330. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/skills/stubs/.ai/fastapi-startkit/fastapi/SKILL.md +0 -0
  331. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/skills/stubs/.ai/fastapi-startkit/inertia/SKILL.md +0 -0
  332. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/storage/__init__.py +0 -0
  333. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/storage/config/__init__.py +0 -0
  334. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/storage/config/storage.py +0 -0
  335. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/storage/data/mime.types +0 -0
  336. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/storage/drivers/__init__.py +0 -0
  337. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/storage/drivers/fake.py +0 -0
  338. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/storage/drivers/local.py +0 -0
  339. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/storage/drivers/s3.py +0 -0
  340. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/storage/file.py +0 -0
  341. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/storage/filestream.py +0 -0
  342. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/storage/helper.py +0 -0
  343. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/storage/providers/provider.py +0 -0
  344. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/storage/storage.py +0 -0
  345. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/support/__init__.py +0 -0
  346. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/support/config.py +0 -0
  347. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/support/dataclass.py +0 -0
  348. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/support/providers/__init__.py +0 -0
  349. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/support/providers/provider.py +0 -0
  350. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/support/string.py +0 -0
  351. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/support/structures.py +0 -0
  352. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/support/uri.py +0 -0
  353. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/testing/__init__.py +0 -0
  354. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/testing/test_case.py +0 -0
  355. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/vite/__init__.py +0 -0
  356. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/vite/config/vite.py +0 -0
  357. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/vite/exceptions.py +0 -0
  358. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/vite/providers/provider.py +0 -0
  359. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/vite/stubs/package.json +0 -0
  360. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/vite/stubs/resources/css/app.css +0 -0
  361. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/vite/stubs/resources/js/app.ts +0 -0
  362. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/vite/stubs/resources/templates/index.html +0 -0
  363. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/vite/stubs/tsconfig.json +0 -0
  364. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/vite/stubs/vite.config.ts +0 -0
  365. {fastapi_startkit-0.63.0 → fastapi_startkit-0.65.0}/src/fastapi_startkit/vite/vite.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: fastapi-startkit
3
- Version: 0.63.0
3
+ Version: 0.65.0
4
4
  Summary: A modular, provider-driven framework for building async Python web applications with FastAPI — bundling a service container, configuration system, an async-first ORM, facades, and a Cleo-powered console.
5
5
  Keywords: fastapi,framework,async,web,asgi,orm,sqlalchemy,pydantic,ioc-container,dependency-injection,service-provider,cli,console,configuration,microservices,starter-kit,boilerplate
6
6
  Author: Bedram Tamang
@@ -12,6 +12,8 @@ Classifier: Operating System :: OS Independent
12
12
  Classifier: Programming Language :: Python :: 3
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Programming Language :: Python :: 3.15
15
17
  Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
16
18
  Requires-Dist: dotty-dict>=1.3.1
17
19
  Requires-Dist: pendulum>=3.1.0,<4.0.0
@@ -20,6 +22,7 @@ Requires-Dist: requests>=2.32.5,<3.0.0
20
22
  Requires-Dist: cleo>=2.1.0,<3.0.0
21
23
  Requires-Dist: dotenv>=0.9.9
22
24
  Requires-Dist: pydantic>=2.12.5
25
+ Requires-Dist: typing-extensions>=4.12.0
23
26
  Requires-Dist: langchain>=1.0.0 ; extra == 'ai'
24
27
  Requires-Dist: langchain-core>=1.0.0 ; extra == 'ai'
25
28
  Requires-Dist: langgraph>=1.0.0 ; extra == 'ai'
@@ -74,8 +77,18 @@ Optional extras enable additional capabilities:
74
77
  fastapi-startkit[fastapi] # FastAPI + Starlette
75
78
  fastapi-startkit[database] # SQLAlchemy async ORM
76
79
  fastapi-startkit[vite] # Jinja2 for Vite integration
80
+ fastapi-startkit[ai] # LangChain agents
77
81
  ```
78
82
 
83
+ ### Python versions
84
+
85
+ Python 3.12, 3.13, 3.14 and 3.15 are supported.
86
+
87
+ > [!NOTE]
88
+ > The `ai` extra cannot be installed on Python 3.15 or newer yet. It depends on `langgraph`, which
89
+ > requires `ormsgpack`, and `ormsgpack` does not support Python 3.15 yet. Use Python 3.14 or older for the
90
+ > `ai` extra. Every other extra works on 3.15.
91
+
79
92
  ## Features
80
93
 
81
94
  - **Service container** — IoC container with `bind`/`make`/`resolve` auto-wiring and lifecycle hooks.
@@ -20,8 +20,18 @@ Optional extras enable additional capabilities:
20
20
  fastapi-startkit[fastapi] # FastAPI + Starlette
21
21
  fastapi-startkit[database] # SQLAlchemy async ORM
22
22
  fastapi-startkit[vite] # Jinja2 for Vite integration
23
+ fastapi-startkit[ai] # LangChain agents
23
24
  ```
24
25
 
26
+ ### Python versions
27
+
28
+ Python 3.12, 3.13, 3.14 and 3.15 are supported.
29
+
30
+ > [!NOTE]
31
+ > The `ai` extra cannot be installed on Python 3.15 or newer yet. It depends on `langgraph`, which
32
+ > requires `ormsgpack`, and `ormsgpack` does not support Python 3.15 yet. Use Python 3.14 or older for the
33
+ > `ai` extra. Every other extra works on 3.15.
34
+
25
35
  ## Features
26
36
 
27
37
  - **Service container** — IoC container with `bind`/`make`/`resolve` auto-wiring and lifecycle hooks.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fastapi-startkit"
3
- version = "0.63.0"
3
+ version = "0.65.0"
4
4
  description = "A modular, provider-driven framework for building async Python web applications with FastAPI — bundling a service container, configuration system, an async-first ORM, facades, and a Cleo-powered console."
5
5
  readme = "README.md"
6
6
  keywords = [
@@ -34,6 +34,8 @@ classifiers = [
34
34
  "Programming Language :: Python :: 3",
35
35
  "Programming Language :: Python :: 3.12",
36
36
  "Programming Language :: Python :: 3.13",
37
+ "Programming Language :: Python :: 3.14",
38
+ "Programming Language :: Python :: 3.15",
37
39
  "Topic :: Software Development :: Libraries :: Application Frameworks",
38
40
  ]
39
41
  dependencies = [
@@ -44,6 +46,7 @@ dependencies = [
44
46
  "cleo>=2.1.0,<3.0.0",
45
47
  "dotenv>=0.9.9",
46
48
  "pydantic>=2.12.5",
49
+ "typing-extensions>=4.12.0",
47
50
  ]
48
51
 
49
52
  [project.urls]
@@ -109,7 +112,7 @@ dev = [
109
112
  "sqlalchemy[asyncio]>=2.0.38",
110
113
  "fastapi[standard]>=0.124.4",
111
114
  "faker>=40.13.0",
112
- "langchain>=1.0.0",
115
+ "langchain>=1.0.0; python_version < '3.15'",
113
116
  "langchain-core>=1.0.0",
114
117
  "basedpyright>=1.31.4",
115
118
  "pyright>=1.1.411",
@@ -44,6 +44,8 @@ class ValidationExceptionHandler:
44
44
  pass
45
45
 
46
46
  async def render(self, request, exc):
47
+ from fastapi_startkit.inertia.constant import Header
48
+
47
49
  accept = request.headers.get("accept", "")
48
50
  content_type = request.headers.get("content-type", "")
49
51
 
@@ -54,6 +56,9 @@ class ValidationExceptionHandler:
54
56
  field = ".".join(str(x) for x in err["loc"][1:])
55
57
  errors.setdefault(field, []).append(err["msg"])
56
58
 
59
+ if request.headers.get(Header.INERTIA):
60
+ return self.redirect_back_with_errors(request, errors)
61
+
57
62
  if wants_json:
58
63
  from fastapi.responses import JSONResponse
59
64
 
@@ -67,3 +72,13 @@ class ValidationExceptionHandler:
67
72
  from fastapi_startkit.fastapi.referer import same_origin_referer
68
73
 
69
74
  return RedirectResponse(url=same_origin_referer(request), status_code=303)
75
+
76
+ @staticmethod
77
+ def redirect_back_with_errors(request, errors: dict):
78
+ from fastapi_startkit.fastapi.referer import same_origin_referer
79
+ from fastapi_startkit.inertia import session
80
+ from fastapi_startkit.inertia.constant import Header
81
+ from fastapi_startkit.inertia.redirect import InertiaRedirect
82
+
83
+ session.put_errors(request, errors, request.headers.get(Header.ERROR_BAG) or session.DEFAULT_BAG)
84
+ return InertiaRedirect(same_origin_referer(request), status_code=303)
@@ -52,7 +52,10 @@ def flash(key: Union[str, Dict[str, Any]], value: Any = None) -> None:
52
52
 
53
53
 
54
54
  def with_errors(errors: ErrorsInput, bag: str = DEFAULT_BAG) -> None:
55
- request = active_request()
55
+ put_errors(active_request(), errors, bag)
56
+
57
+
58
+ def put_errors(request: Request, errors: ErrorsInput, bag: str = DEFAULT_BAG) -> None:
56
59
  bags = dict(store(request).get(ERRORS) or {})
57
60
  bags[bag] = ValidationErrors(bags.get(bag)).merge(ValidationErrors.make(errors)).all()
58
61
  put(request, ERRORS, bags)
@@ -0,0 +1,140 @@
1
+ import html
2
+ import json
3
+ import re
4
+ from collections.abc import Mapping, Sequence
5
+ from typing import Any, Optional, Self
6
+
7
+ from starlette.types import ASGIApp, Receive, Scope, Send
8
+
9
+ from fastapi_startkit.inertia.constant import Header
10
+
11
+ MISSING: Any = object()
12
+ SCRIPT_PAGE = re.compile(r"<script\b[^>]*\bdata-page=[\"'][^\"']*[\"'][^>]*>(.*?)</script>", re.DOTALL)
13
+ ATTRIBUTE_PAGE = re.compile(r"\bdata-page=(?:\"([^\"]*)\"|'([^']*)')")
14
+
15
+
16
+ class FakeSessionMiddleware:
17
+ def __init__(self, app: ASGIApp, session: Optional[dict] = None):
18
+ self.app = app
19
+ self.session = session if session is not None else {}
20
+
21
+ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
22
+ if scope["type"] in ("http", "websocket"):
23
+ scope["session"] = self.session
24
+ await self.app(scope, receive, send)
25
+
26
+
27
+ def response_text(response: Any) -> str:
28
+ text = getattr(response, "text", None)
29
+ if isinstance(text, str):
30
+ return text
31
+ body = getattr(response, "body", b"")
32
+ return body.decode() if isinstance(body, bytes) else str(body)
33
+
34
+
35
+ def is_json(response: Any) -> bool:
36
+ return bool(response.headers.get(Header.INERTIA)) or "json" in response.headers.get("content-type", "")
37
+
38
+
39
+ def extract_page(response: Any) -> dict:
40
+ text = response_text(response)
41
+ if is_json(response):
42
+ return json.loads(text)
43
+ script = SCRIPT_PAGE.search(text)
44
+ if script:
45
+ return json.loads(script.group(1))
46
+ attribute = ATTRIBUTE_PAGE.search(text)
47
+ if attribute:
48
+ return json.loads(html.unescape(attribute.group(1) or attribute.group(2)))
49
+ raise AssertionError(f"Response does not contain an Inertia page: {text[:200]!r}")
50
+
51
+
52
+ def ensure(condition: bool, message: str) -> None:
53
+ if not condition:
54
+ raise AssertionError(message)
55
+
56
+
57
+ def lookup(value: Any, path: str) -> Any:
58
+ for segment in path.split("."):
59
+ if isinstance(value, Mapping) and segment in value:
60
+ value = value[segment]
61
+ elif isinstance(value, Sequence) and not isinstance(value, str) and segment.isdigit():
62
+ if int(segment) >= len(value):
63
+ return MISSING
64
+ value = value[int(segment)]
65
+ else:
66
+ return MISSING
67
+ return value
68
+
69
+
70
+ class AssertablePage:
71
+ def __init__(self, page: dict):
72
+ self.page = page
73
+
74
+ @classmethod
75
+ def from_response(cls, response: Any) -> "AssertablePage":
76
+ return cls(extract_page(response))
77
+
78
+ @property
79
+ def props(self) -> dict:
80
+ return self.page.get("props", {})
81
+
82
+ def prop(self, path: str) -> Any:
83
+ value = lookup(self.props, path)
84
+ ensure(value is not MISSING, f"Expected prop {path!r} to exist in props {self.props!r}")
85
+ return value
86
+
87
+ def component(self, name: str) -> Self:
88
+ actual = self.page.get("component")
89
+ ensure(actual == name, f"Expected component {name!r}, got {actual!r}")
90
+ return self
91
+
92
+ def url(self, url: str) -> Self:
93
+ actual = self.page.get("url")
94
+ ensure(actual == url, f"Expected url {url!r}, got {actual!r}")
95
+ return self
96
+
97
+ def version(self, version: str) -> Self:
98
+ actual = self.page.get("version")
99
+ ensure(actual == version, f"Expected version {version!r}, got {actual!r}")
100
+ return self
101
+
102
+ def has(self, path: str) -> Self:
103
+ self.prop(path)
104
+ return self
105
+
106
+ def has_count(self, path: str, count: int) -> Self:
107
+ value = self.prop(path)
108
+ size = len(value) if isinstance(value, (Mapping, Sequence)) and not isinstance(value, str) else None
109
+ ensure(size == count, f"Expected prop {path!r} to have {count} items, got {size}")
110
+ return self
111
+
112
+ def missing(self, path: str) -> Self:
113
+ value = lookup(self.props, path)
114
+ ensure(value is MISSING, f"Expected prop {path!r} to be missing, got {value!r}")
115
+ return self
116
+
117
+ def equals(self, path: str, expected: Any) -> Self:
118
+ value = self.prop(path)
119
+ ensure(value == expected, f"Expected prop {path!r} to equal {expected!r}, got {value!r}")
120
+ return self
121
+
122
+ def deferred(self, group: str, props: Sequence[str]) -> Self:
123
+ groups = self.page.get("deferredProps", {})
124
+ actual = groups.get(group)
125
+ ensure(
126
+ actual is not None and sorted(actual) == sorted(props),
127
+ f"Expected deferred group {group!r} to be {sorted(props)!r}, got {actual!r} in {groups!r}",
128
+ )
129
+ return self
130
+
131
+ def flash(self, key: str, value: Any = MISSING) -> Self:
132
+ flash = self.page.get("flash", {})
133
+ ensure(key in flash, f"Expected flash {key!r} to exist in {flash!r}")
134
+ if value is not MISSING:
135
+ ensure(flash[key] == value, f"Expected flash {key!r} to equal {value!r}, got {flash[key]!r}")
136
+ return self
137
+
138
+
139
+ def assert_inertia(response: Any) -> AssertablePage:
140
+ return AssertablePage.from_response(response)
@@ -33,14 +33,13 @@ class Collection(BaseCollection, Generic[T]):
33
33
  first = self._items[0]
34
34
  for relation in relations:
35
35
  relationship = getattr(first.__class__, relation)
36
- result_set = await relationship.get_related(None, self)
37
- if result_set:
38
- map_related = relationship.map_related(result_set)
39
- for model in self._items:
40
- if isinstance(result_set, Collection):
41
- relationship.register_related(relation, model, map_related)
42
- else:
43
- # load() only runs on model collections; T is generic.
44
- model.add_relation({relation: map_related or None}) # type: ignore
36
+ result_set = await relationship.get_related(first.get_builder(), self)
37
+ map_related = relationship.map_related(result_set)
38
+ for model in self._items:
39
+ if isinstance(result_set, Collection):
40
+ relationship.register_related(relation, model, map_related)
41
+ else:
42
+ # load() only runs on model collections; T is generic.
43
+ model.add_relation({relation: map_related or None}) # type: ignore
45
44
 
46
45
  return self
@@ -0,0 +1,22 @@
1
+ class ModelNotFoundException(Exception):
2
+ is_http_exception = True
3
+
4
+ def __init__(self, message="Model Not Found"):
5
+ super().__init__(message)
6
+ self.message = message
7
+
8
+ def get_response(self):
9
+ return self.message
10
+
11
+ def get_status(self):
12
+ return 404
13
+
14
+
15
+ class LazyLoadingViolation(Exception):
16
+ def __init__(self, model: object, relation: str | None):
17
+ self.model = type(model).__name__
18
+ self.relation = relation
19
+ super().__init__(
20
+ f"Attempted to lazy load [{relation}] on model [{self.model}]. "
21
+ f'Eager load it with {self.model}.with_("{relation}") or await the model\'s load("{relation}") first.'
22
+ )
@@ -3,6 +3,7 @@ import pendulum
3
3
  import datetime
4
4
  from decimal import Decimal
5
5
  from enum import Enum
6
+ from inspect import get_annotations
6
7
  from dataclasses import dataclass, field
7
8
  from collections.abc import Callable
8
9
  from typing import Any, get_args, get_type_hints, Optional
@@ -208,7 +209,7 @@ class Caster:
208
209
  except NameError:
209
210
  annotations = {}
210
211
  for klass in reversed(model.__mro__):
211
- for name, hint in vars(klass).get("__annotations__", {}).items():
212
+ for name, hint in get_annotations(klass).items():
212
213
  if not isinstance(getattr(model, name, None), BaseRelationship):
213
214
  annotations[name] = hint
214
215
 
@@ -107,6 +107,10 @@ class Model(Attribute, Relationship, ObservesEvents):
107
107
  def get_related(self, key: str):
108
108
  return getattr(self.__class__, key)
109
109
 
110
+ async def load(self, *relations: str) -> Self:
111
+ await self.new_collection([self]).load(*relations)
112
+ return self
113
+
110
114
  @classmethod
111
115
  def with_(cls, *eagers) -> "QueryBuilder[Self]":
112
116
  return cls.query().with_(*eagers)
@@ -1,6 +1,5 @@
1
1
  import inspect
2
2
 
3
- from fastapi_startkit.masoniteorm.collection import Collection
4
3
  from fastapi_startkit.masoniteorm.query.EagerRelation import EagerRelations
5
4
 
6
5
 
@@ -9,6 +8,9 @@ class EagerLoadMixin:
9
8
  self._eager_relation = EagerRelations()
10
9
 
11
10
  async def _load_eagers(self, models, model):
11
+ if not models:
12
+ return
13
+
12
14
  for eager_load in self._eager_relation.get_eagers():
13
15
  if isinstance(eager_load, dict):
14
16
  # Nested or callback eagers
@@ -53,15 +55,9 @@ class EagerLoadMixin:
53
55
  )
54
56
 
55
57
  async def _register_relationships_to_model(self, related, related_result, models, relation_key):
56
- if related_result and isinstance(models, Collection):
57
- map_related = self._map_related(related_result, related)
58
- for model in models:
59
- if isinstance(related_result, Collection):
60
- related.register_related(relation_key, model, map_related)
61
- else:
62
- model.add_relation({relation_key: map_related or None})
63
- else:
64
- models.add_relation({relation_key: related_result or None})
58
+ map_related = self._map_related(related_result, related)
59
+ for model in models:
60
+ related.register_related(relation_key, model, map_related)
65
61
  return self
66
62
 
67
63
  def _map_related(self, related_result, related):
@@ -1,12 +1,27 @@
1
+ import os
2
+ import typing
3
+ import warnings
4
+ from typing import TYPE_CHECKING, Any, ForwardRef, Generic, Self, get_args, overload
5
+
6
+ from typing_extensions import TypeVar
7
+
1
8
  from fastapi_startkit.masoniteorm.models import registry
9
+ from ..collection import Collection
10
+ from ..exceptions import LazyLoadingViolation
2
11
 
12
+ if TYPE_CHECKING:
13
+ from ..models.model import Model
14
+
15
+ TModel = TypeVar("TModel", bound="Model", default="Model")
16
+ TResult = TypeVar("TResult", default=Any)
17
+
18
+ type SingleResult[T] = T | None
19
+ type ManyResult[T] = Collection[T]
3
20
 
4
- class BaseRelationship:
5
- def __init__(self, fn: str | list[str], local_key=None, foreign_key=None):
6
- if not isinstance(fn, str):
7
- raise TypeError(f"Relationship {self.__class__.__name__} expects a string as the first argument")
8
- fn_str: str = fn # For type checking
9
- self.fn = lambda: registry.Registry.resolve(fn_str)
21
+
22
+ class BaseRelationship(Generic[TModel, TResult]):
23
+ def __init__(self, fn: str | None = None, local_key=None, foreign_key=None):
24
+ self.bind_model(fn)
10
25
 
11
26
  self.local_key = local_key
12
27
  self.foreign_key = foreign_key
@@ -15,11 +30,54 @@ class BaseRelationship:
15
30
  def __set_name__(self, cls, name):
16
31
  self.attribute = name
17
32
  self.owner_class = cls
33
+ if "_model_name" in self.__dict__:
34
+ self.model_reference()
35
+
36
+ def bind_model(self, fn: str | None) -> None:
37
+ if fn is not None and not isinstance(fn, str):
38
+ raise TypeError(f"Relationship {self.__class__.__name__} expects a string as the first argument")
39
+ if fn is not None:
40
+ klass = self.__class__.__name__
41
+ warnings.warn(
42
+ f'Passing the related model as {klass}("{fn}", ...) is deprecated and will be removed in 1.x; '
43
+ f'declare it as {klass}["{fn}"](...) instead.',
44
+ DeprecationWarning,
45
+ skip_file_prefixes=(os.path.dirname(__file__), typing.__file__),
46
+ )
47
+ self._model_name = fn
48
+ self.fn = self.related_model
49
+
50
+ def related_model(self) -> type:
51
+ model = self.model_reference()
52
+ return registry.Registry.resolve(model) if isinstance(model, str) else model
53
+
54
+ def model_reference(self) -> str | type:
55
+ if self._model_name is not None:
56
+ return self._model_name
57
+
58
+ alias = self.__dict__.get("__orig_class__")
59
+ if alias is None:
60
+ klass = self.__class__.__name__
61
+ owner = self.__dict__.get("owner_class")
62
+ subject = f"{owner.__name__}.{self.__dict__.get('attribute')}" if owner else klass
63
+ raise TypeError(f'{subject} needs its related model: declare it as {klass}["Model"](...)')
64
+
65
+ model = get_args(alias)[0]
66
+ return model.__forward_arg__ if isinstance(model, ForwardRef) else model
18
67
 
19
68
  def get_builder(self):
20
69
  return self.fn()().get_builder()
21
70
 
22
- def __get__(self, instance, owner):
71
+ @overload
72
+ def __get__(self, instance: None, owner: Any) -> Self: ...
73
+ @overload
74
+ def __get__(self: "BaseRelationship[Model, Any]", instance: object, owner: Any) -> Any: ...
75
+ @overload
76
+ def __get__(self, instance: object, owner: Any) -> TResult: ...
77
+ def __get__(self, instance, owner) -> Any:
78
+ return self.access(instance, owner)
79
+
80
+ def access(self, instance, owner):
23
81
  """
24
82
  This method is called when the decorated method is accessed.
25
83
 
@@ -43,7 +101,7 @@ class BaseRelationship:
43
101
  if self.attribute in instance._relationships:
44
102
  return instance._relationships[self.attribute]
45
103
 
46
- return self.apply_query(self.get_builder(), instance)
104
+ raise LazyLoadingViolation(instance, self.attribute)
47
105
 
48
106
  def __getattr__(self, attribute):
49
107
  return getattr(self.get_builder(), attribute)
@@ -1,16 +1,14 @@
1
1
  from typing import cast
2
2
 
3
3
  from ..collection import Collection
4
- from . import BaseRelationship
5
- from fastapi_startkit.masoniteorm.models import registry
4
+ from .BaseRelationship import BaseRelationship, SingleResult, TModel
6
5
 
7
6
 
8
- class BelongsTo(BaseRelationship):
7
+ class BelongsTo(BaseRelationship[TModel, SingleResult[TModel]]):
9
8
  """Belongs To Relationship Class."""
10
9
 
11
- def __init__(self, fn: str, local_key=None, foreign_key=None):
12
- # If user provides string instead of Model, we will resolve it here
13
- self.fn = lambda: registry.Registry.resolve(fn)
10
+ def __init__(self, fn: str | None = None, local_key=None, foreign_key=None):
11
+ self.bind_model(fn)
14
12
 
15
13
  self.local_key = local_key or "id"
16
14
  self.foreign_key = foreign_key
@@ -1,18 +1,17 @@
1
1
  import pendulum
2
2
  from inflection import singularize
3
3
 
4
- from fastapi_startkit.masoniteorm.models import registry
5
- from .BaseRelationship import BaseRelationship
4
+ from .BaseRelationship import BaseRelationship, ManyResult, TModel
6
5
  from ..collection import Collection
7
6
  from ..models.pivot import Pivot
8
7
 
9
8
 
10
- class BelongsToMany(BaseRelationship):
9
+ class BelongsToMany(BaseRelationship[TModel, ManyResult[TModel]]):
11
10
  """Has Many Relationship Class."""
12
11
 
13
12
  def __init__(
14
13
  self,
15
- fn: str,
14
+ fn: str | None = None,
16
15
  local_foreign_key=None,
17
16
  other_foreign_key=None,
18
17
  local_owner_key=None,
@@ -23,7 +22,7 @@ class BelongsToMany(BaseRelationship):
23
22
  attribute="pivot",
24
23
  with_fields=[],
25
24
  ):
26
- self.fn = lambda: registry.Registry.resolve(fn)
25
+ self.bind_model(fn)
27
26
 
28
27
  self.local_key = local_foreign_key
29
28
  self.foreign_key = other_foreign_key
@@ -1,8 +1,8 @@
1
- from .BaseRelationship import BaseRelationship
1
+ from .BaseRelationship import BaseRelationship, ManyResult, TModel
2
2
  from ..collection import Collection
3
3
 
4
4
 
5
- class HasMany(BaseRelationship):
5
+ class HasMany(BaseRelationship[TModel, ManyResult[TModel]]):
6
6
  """Has Many Relationship Class."""
7
7
 
8
8
  def apply_query(self, foreign, owner):
@@ -26,7 +26,7 @@ class HasMany(BaseRelationship):
26
26
  return self
27
27
 
28
28
  def register_related(self, key, model, collection):
29
- model.add_relation({key: collection.get(getattr(model, self.local_key)) or Collection()})
29
+ model.add_relation({key: Collection(collection.get(getattr(model, self.local_key)) or [])})
30
30
 
31
31
  def map_related(self, related_result):
32
32
  return related_result.group_by(self.foreign_key)
@@ -1,9 +1,10 @@
1
1
  from fastapi_startkit.masoniteorm.models import registry
2
- from .BaseRelationship import BaseRelationship
2
+ from ..exceptions import LazyLoadingViolation
3
+ from .BaseRelationship import BaseRelationship, ManyResult, TModel
3
4
  from ..collection import Collection
4
5
 
5
6
 
6
- class HasManyThrough(BaseRelationship):
7
+ class HasManyThrough(BaseRelationship[TModel, ManyResult[TModel]]):
7
8
  """HasManyThrough Relationship Class."""
8
9
 
9
10
  def __init__(
@@ -43,18 +44,14 @@ class HasManyThrough(BaseRelationship):
43
44
  self.other_owner_key = self.other_owner_key or "id"
44
45
  return self
45
46
 
46
- def __get__(self, instance, owner):
47
+ def access(self, instance, owner):
47
48
  if instance is None or not instance.is_loaded():
48
49
  return self
49
50
 
50
51
  if instance.relationship_loaded(self.attribute):
51
52
  return instance.get_relationship(self.attribute)
52
53
 
53
- return self.apply_related_query(
54
- distant_builder=self.get_distance_builder(),
55
- intermediary_builder=self.get_intermediary_builder(),
56
- owner=instance,
57
- )
54
+ raise LazyLoadingViolation(instance, self.attribute)
58
55
 
59
56
  def apply_related_query(self, distant_builder, intermediary_builder, owner):
60
57
  distant_table = distant_builder.get_table_name()
@@ -96,11 +93,11 @@ class HasManyThrough(BaseRelationship):
96
93
  return builder
97
94
 
98
95
  def register_related(self, key, model, collection):
99
- related = collection.get(getattr(model, self.local_owner_key), None)
100
- if related and not isinstance(related, Collection):
96
+ related = collection.get(getattr(model, self.local_owner_key)) or Collection()
97
+ if not isinstance(related, Collection):
101
98
  related = Collection(related)
102
99
 
103
- model.add_relation({key: related if related else None})
100
+ model.add_relation({key: related})
104
101
 
105
102
  async def get_related(self, query, relation, eagers=None, callback=None):
106
103
  distant_builder = self.get_distance_builder()
@@ -1,13 +1,12 @@
1
1
  from ..collection import Collection
2
- from .BaseRelationship import BaseRelationship
3
- from fastapi_startkit.masoniteorm.models import registry
2
+ from .BaseRelationship import BaseRelationship, SingleResult, TModel
4
3
 
5
4
 
6
- class HasOne(BaseRelationship):
5
+ class HasOne(BaseRelationship[TModel, SingleResult[TModel]]):
7
6
  """Has One Relationship Class."""
8
7
 
9
- def __init__(self, fn: str, foreign_key=None, local_key=None):
10
- self.fn = lambda: registry.Registry.resolve(fn)
8
+ def __init__(self, fn: str | None = None, foreign_key=None, local_key=None):
9
+ self.bind_model(fn)
11
10
 
12
11
  self.local_key = local_key or "id"
13
12
  self.foreign_key = foreign_key