fastapi-startkit 0.44.0__tar.gz → 0.45.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 (394) hide show
  1. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/PKG-INFO +1 -1
  2. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/pyproject.toml +1 -1
  3. fastapi_startkit-0.45.0/src/fastapi_startkit/fastapi/testing/__init__.py +8 -0
  4. fastapi_startkit-0.45.0/src/fastapi_startkit/fastapi/testing/assertable_json.py +332 -0
  5. fastapi_startkit-0.45.0/src/fastapi_startkit/fastapi/testing/test_case.py +35 -0
  6. fastapi_startkit-0.45.0/src/fastapi_startkit/fastapi/testing/test_response.py +102 -0
  7. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/model.py +4 -0
  8. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/grammars/PostgresGrammar.py +6 -0
  9. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/registry.py +3 -0
  10. fastapi_startkit-0.45.0/src/fastapi_startkit/skills/stubs/.ai/fastapi-startkit/fastapi/SKILL.md +149 -0
  11. fastapi_startkit-0.45.0/src/fastapi_startkit/skills/stubs/.ai/fastapi-startkit/inertia/SKILL.md +333 -0
  12. fastapi_startkit-0.44.0/src/fastapi_startkit/fastapi/testing/__init__.py +0 -3
  13. fastapi_startkit-0.44.0/src/fastapi_startkit/fastapi/testing/test_case.py +0 -31
  14. fastapi_startkit-0.44.0/src/fastapi_startkit/skills/stubs/.ai/fastapi-startkit/fastapi/SKILL.md +0 -109
  15. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/.DS_Store +0 -0
  16. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/__init__.py +0 -0
  17. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/__init__.py +0 -0
  18. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/agent.py +0 -0
  19. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/audio.py +0 -0
  20. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/audio_factory.py +0 -0
  21. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/config.py +0 -0
  22. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/decorators.py +0 -0
  23. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/document.py +0 -0
  24. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/image.py +0 -0
  25. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/image_factory.py +0 -0
  26. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/providers/__init__.py +0 -0
  27. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/providers/ai_provider.py +0 -0
  28. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/response.py +0 -0
  29. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/application.py +0 -0
  30. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/__init__.py +0 -0
  31. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/auth.py +0 -0
  32. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/channels.py +0 -0
  33. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/config.py +0 -0
  34. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/drivers/__init__.py +0 -0
  35. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/drivers/log_driver.py +0 -0
  36. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/drivers/reverb_driver.py +0 -0
  37. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/event.py +0 -0
  38. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/helpers.py +0 -0
  39. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/manager.py +0 -0
  40. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/provider.py +0 -0
  41. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/reverb/__init__.py +0 -0
  42. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/reverb/channel_manager.py +0 -0
  43. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/reverb/connection.py +0 -0
  44. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/reverb/server.py +0 -0
  45. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/stubs/__init__.py +0 -0
  46. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/stubs/channels.py +0 -0
  47. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/carbon/__init__.py +0 -0
  48. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/carbon/carbon.py +0 -0
  49. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/config/__init__.py +0 -0
  50. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/config/app.py +0 -0
  51. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/configuration/Configuration.py +0 -0
  52. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/configuration/__init__.py +0 -0
  53. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/configuration/config.py +0 -0
  54. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/configuration/helpers.py +0 -0
  55. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/configuration/providers/ConfigurationProvider.py +0 -0
  56. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/configuration/providers/__init__.py +0 -0
  57. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/console/__init__.py +0 -0
  58. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/console/application.py +0 -0
  59. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/console/can_override_config.py +0 -0
  60. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/console/can_override_default_options.py +0 -0
  61. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/console/command.py +0 -0
  62. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/console/publish_command.py +0 -0
  63. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/container/__init__.py +0 -0
  64. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/container/container.py +0 -0
  65. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/environment/__init__.py +0 -0
  66. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/environment/environment.py +0 -0
  67. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/exceptions/__init__.py +0 -0
  68. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/exceptions/exceptions.py +0 -0
  69. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/exceptions/handler.py +0 -0
  70. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/AI.py +0 -0
  71. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/AI.pyi +0 -0
  72. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Cache.py +0 -0
  73. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Config.py +0 -0
  74. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Config.pyi +0 -0
  75. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Dump.py +0 -0
  76. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Dump.pyi +0 -0
  77. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Facade.py +0 -0
  78. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Gate.py +0 -0
  79. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Gate.pyi +0 -0
  80. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Hash.py +0 -0
  81. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Hash.pyi +0 -0
  82. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Loader.py +0 -0
  83. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Loader.pyi +0 -0
  84. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Mail.py +0 -0
  85. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Mail.pyi +0 -0
  86. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Notification.py +0 -0
  87. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Notification.pyi +0 -0
  88. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Queue.py +0 -0
  89. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Queue.pyi +0 -0
  90. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/RateLimiter.py +0 -0
  91. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/RateLimiter.pyi +0 -0
  92. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Request.py +0 -0
  93. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Request.pyi +0 -0
  94. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Response.py +0 -0
  95. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Response.pyi +0 -0
  96. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Session.py +0 -0
  97. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Session.pyi +0 -0
  98. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Url.py +0 -0
  99. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Url.pyi +0 -0
  100. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/View.py +0 -0
  101. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/View.pyi +0 -0
  102. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Vite.py +0 -0
  103. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Vite.pyi +0 -0
  104. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/__init__.py +0 -0
  105. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/__init__.py +0 -0
  106. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/commands/__init__.py +0 -0
  107. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/commands/serve_command.py +0 -0
  108. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/config/__init__.py +0 -0
  109. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/config/fastapi.py +0 -0
  110. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/exceptions.py +0 -0
  111. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/providers/fastapi_provider.py +0 -0
  112. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/requests/model.py +0 -0
  113. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/routers/router.py +0 -0
  114. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/helpers/app.py +0 -0
  115. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/helpers/dataclass.py +0 -0
  116. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/inertia/__init__.py +0 -0
  117. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/inertia/constant.py +0 -0
  118. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/inertia/context.py +0 -0
  119. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/inertia/inertia.py +0 -0
  120. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/inertia/middleware.py +0 -0
  121. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/inertia/props/props.py +0 -0
  122. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/inertia/provider.py +0 -0
  123. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/jsonapi/__init__.py +0 -0
  124. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/jsonapi/response.py +0 -0
  125. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/loader/Loader.py +0 -0
  126. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/loader/__init__.py +0 -0
  127. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/ChannelFactory.py +0 -0
  128. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/__init__.py +0 -0
  129. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/BaseChannel.py +0 -0
  130. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/DailyChannel.py +0 -0
  131. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/MultiBaseChannel.py +0 -0
  132. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/SingleChannel.py +0 -0
  133. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/SlackChannel.py +0 -0
  134. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/StackChannel.py +0 -0
  135. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/SyslogChannel.py +0 -0
  136. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/TerminalChannel.py +0 -0
  137. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/__init__.py +0 -0
  138. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/config/__init__.py +0 -0
  139. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/config/channels.py +0 -0
  140. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/config/logging.py +0 -0
  141. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/drivers/BaseDriver.py +0 -0
  142. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/drivers/LogSingleDriver.py +0 -0
  143. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/drivers/LogSlackDriver.py +0 -0
  144. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/drivers/LogSyslogDriver.py +0 -0
  145. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/drivers/LogTerminalDriver.py +0 -0
  146. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/drivers/__init__.py +0 -0
  147. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/factory.py +0 -0
  148. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/file.py +0 -0
  149. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/handler.py +0 -0
  150. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/listeners.py +0 -0
  151. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/logger.py +0 -0
  152. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/managers/LoggingManager.py +0 -0
  153. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/managers/__init__.py +0 -0
  154. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/providers/__init__.py +0 -0
  155. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/providers/log_provider.py +0 -0
  156. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/__init__.py +0 -0
  157. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/collection/Collection.py +0 -0
  158. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/collection/__init__.py +0 -0
  159. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/DBMigrateCommand.py +0 -0
  160. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/DBSeedCommand.py +0 -0
  161. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MakeMigrationCommand.py +0 -0
  162. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MakeModelCommand.py +0 -0
  163. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MakeModelDocstringCommand.py +0 -0
  164. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MakeObserverCommand.py +0 -0
  165. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MakeSeedCommand.py +0 -0
  166. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MigrateFreshCommand.py +0 -0
  167. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MigrateRefreshCommand.py +0 -0
  168. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MigrateResetCommand.py +0 -0
  169. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MigrateRollbackCommand.py +0 -0
  170. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MigrateStatusCommand.py +0 -0
  171. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/ShellCommand.py +0 -0
  172. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/__init__.py +0 -0
  173. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/stubs/create_migration.stub +0 -0
  174. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/stubs/create_seed.stub +0 -0
  175. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/stubs/model.stub +0 -0
  176. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/stubs/observer.stub +0 -0
  177. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/stubs/table_migration.stub +0 -0
  178. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/config/__init__.py +0 -0
  179. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/config/config.py +0 -0
  180. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/config/database.py +0 -0
  181. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/connections/connection.py +0 -0
  182. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/connections/factory.py +0 -0
  183. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/connections/manager.py +0 -0
  184. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/connections/mysql_connection.py +0 -0
  185. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/connections/postgres_connection.py +0 -0
  186. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/connections/sqlite_connection.py +0 -0
  187. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/exceptions.py +0 -0
  188. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/expressions/__init__.py +0 -0
  189. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/expressions/expressions.py +0 -0
  190. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/facades/DB.py +0 -0
  191. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/facades/Schema.py +0 -0
  192. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/facades/__init__.py +0 -0
  193. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/factory/__init__.py +0 -0
  194. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/factory/factory.py +0 -0
  195. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/helpers/__init__.py +0 -0
  196. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/helpers/misc.py +0 -0
  197. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/migrations/Migration.py +0 -0
  198. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/migrations/Migrator.py +0 -0
  199. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/migrations/__init__.py +0 -0
  200. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/MigrationModel.py +0 -0
  201. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/__init__.py +0 -0
  202. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/attribute.py +0 -0
  203. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/builder.py +0 -0
  204. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/caster.py +0 -0
  205. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/fields.py +0 -0
  206. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/observer.py +0 -0
  207. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/pivot.py +0 -0
  208. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/registry.py +0 -0
  209. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/relationship.py +0 -0
  210. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/observers/ObservesEvents.py +0 -0
  211. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/observers/__init__.py +0 -0
  212. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/pagination/BasePaginator.py +0 -0
  213. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/pagination/LengthAwarePaginator.py +0 -0
  214. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/pagination/SimplePaginator.py +0 -0
  215. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/pagination/__init__.py +0 -0
  216. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/providers/DatabaseProvider.py +0 -0
  217. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/providers/__init__.py +0 -0
  218. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/EagerLoadMixin.py +0 -0
  219. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/EagerRelation.py +0 -0
  220. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/__init__.py +0 -0
  221. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/grammars/BaseGrammar.py +0 -0
  222. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/grammars/MSSQLGrammar.py +0 -0
  223. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/grammars/MySQLGrammar.py +0 -0
  224. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/grammars/SQLiteGrammar.py +0 -0
  225. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/grammars/__init__.py +0 -0
  226. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/processors/MSSQLPostProcessor.py +0 -0
  227. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/processors/MySQLPostProcessor.py +0 -0
  228. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/processors/PostgresPostProcessor.py +0 -0
  229. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/processors/SQLitePostProcessor.py +0 -0
  230. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/processors/__init__.py +0 -0
  231. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/support.py +0 -0
  232. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/BaseRelationship.py +0 -0
  233. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/BelongsTo.py +0 -0
  234. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/BelongsToMany.py +0 -0
  235. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/HasMany.py +0 -0
  236. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/HasManyThrough.py +0 -0
  237. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/HasOne.py +0 -0
  238. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/HasOneThrough.py +0 -0
  239. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/MorphMany.py +0 -0
  240. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/MorphOne.py +0 -0
  241. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/MorphTo.py +0 -0
  242. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/MorphToMany.py +0 -0
  243. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/__init__.py +0 -0
  244. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/Blueprint.py +0 -0
  245. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/Column.py +0 -0
  246. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/ColumnDiff.py +0 -0
  247. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/Constraint.py +0 -0
  248. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/ForeignKeyConstraint.py +0 -0
  249. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/Index.py +0 -0
  250. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/Table.py +0 -0
  251. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/TableDiff.py +0 -0
  252. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/__init__.py +0 -0
  253. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/platforms/MSSQLPlatform.py +0 -0
  254. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/platforms/MySQLPlatform.py +0 -0
  255. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/platforms/Platform.py +0 -0
  256. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/platforms/PostgresPlatform.py +0 -0
  257. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/platforms/SQLitePlatform.py +0 -0
  258. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/platforms/__init__.py +0 -0
  259. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/schema.py +0 -0
  260. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/seeds/Seeder.py +0 -0
  261. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/seeds/__init__.py +0 -0
  262. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/stubs/create-migration.html +0 -0
  263. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/stubs/table-migration.html +0 -0
  264. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/testing/__init__.py +0 -0
  265. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/testing/transaction.py +0 -0
  266. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/.gitignore +0 -0
  267. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/CACHEDIR.TAG +0 -0
  268. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/README.md +0 -0
  269. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/v/cache/lastfailed +0 -0
  270. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/v/cache/nodeids +0 -0
  271. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/__init__.py +0 -0
  272. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/config/database.py +0 -0
  273. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/config.py +0 -0
  274. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/exceptions.py +0 -0
  275. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/factories/Factory.py +0 -0
  276. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/factories/__init__.py +0 -0
  277. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/schema/Schema.py +0 -0
  278. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/scopes/BaseScope.py +0 -0
  279. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/scopes/SoftDeleteScope.py +0 -0
  280. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/scopes/SoftDeletesMixin.py +0 -0
  281. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/scopes/UUIDPrimaryKeyMixin.py +0 -0
  282. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/scopes/UUIDPrimaryKeyScope.py +0 -0
  283. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/scopes/__init__.py +0 -0
  284. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/scopes/scope.py +0 -0
  285. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/testing/BaseTestCaseSelectGrammar.py +0 -0
  286. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/testing/Database.py +0 -0
  287. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/testing/TestCase.py +0 -0
  288. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/testing/__init__.py +0 -0
  289. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/User.py +0 -0
  290. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/connections/test_base_connections.py +0 -0
  291. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/eagers/test_eager.py +0 -0
  292. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/models/test_models.py +0 -0
  293. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/builder/test_mssql_query_builder.py +0 -0
  294. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/builder/test_mssql_query_builder_relationships.py +0 -0
  295. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_delete_grammar.py +0 -0
  296. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_insert_grammar.py +0 -0
  297. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_qmark.py +0 -0
  298. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_select_grammar.py +0 -0
  299. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_update_grammar.py +0 -0
  300. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/schema/test_mssql_schema_builder.py +0 -0
  301. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/schema/test_mssql_schema_builder_alter.py +0 -0
  302. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/builder/test_mysql_builder_transaction.py +0 -0
  303. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/builder/test_query_builder.py +0 -0
  304. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/builder/test_query_builder_scopes.py +0 -0
  305. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/builder/test_transactions.py +0 -0
  306. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/connections/test_mysql_connection_selects.py +0 -0
  307. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_delete_grammar.py +0 -0
  308. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_insert_grammar.py +0 -0
  309. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_qmark.py +0 -0
  310. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_select_grammar.py +0 -0
  311. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_update_grammar.py +0 -0
  312. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/model/test_accessors_and_mutators.py +0 -0
  313. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/model/test_model.py +0 -0
  314. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/relationships/test_belongs_to_many.py +0 -0
  315. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/relationships/test_has_many_through.py +0 -0
  316. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/relationships/test_has_one_through.py +0 -0
  317. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/relationships/test_relationships.py +0 -0
  318. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/schema/test_mysql_schema_builder.py +0 -0
  319. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/schema/test_mysql_schema_builder_alter.py +0 -0
  320. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/scopes/test_can_use_global_scopes.py +0 -0
  321. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/scopes/test_can_use_scopes.py +0 -0
  322. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/scopes/test_soft_delete.py +0 -0
  323. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/builder/test_postgres_query_builder.py +0 -0
  324. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/builder/test_postgres_transaction.py +0 -0
  325. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/grammar/test_delete_grammar.py +0 -0
  326. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/grammar/test_insert_grammar.py +0 -0
  327. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/grammar/test_select_grammar.py +0 -0
  328. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/grammar/test_update_grammar.py +0 -0
  329. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/relationships/test_postgres_relationships.py +0 -0
  330. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/schema/test_postgres_schema_builder.py +0 -0
  331. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/schema/test_postgres_schema_builder_alter.py +0 -0
  332. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/scopes/test_default_global_scopes.py +0 -0
  333. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/seeds/test_seeds.py +0 -0
  334. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/utils.py +0 -0
  335. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/__init__.py +0 -0
  336. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/argument.py +0 -0
  337. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/prompt.py +0 -0
  338. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/protocol.py +0 -0
  339. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/providers/__init__.py +0 -0
  340. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/providers/mcp_provider.py +0 -0
  341. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/request.py +0 -0
  342. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/resource.py +0 -0
  343. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/response.py +0 -0
  344. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/server.py +0 -0
  345. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/tool.py +0 -0
  346. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/process/__init__.py +0 -0
  347. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/process/exception.py +0 -0
  348. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/process/fake.py +0 -0
  349. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/process/process.py +0 -0
  350. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/process/result.py +0 -0
  351. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/providers/Provider.py +0 -0
  352. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/providers/__init__.py +0 -0
  353. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/providers/app_provider.py +0 -0
  354. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/__init__.py +0 -0
  355. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/adapters/__init__.py +0 -0
  356. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/adapters/base.py +0 -0
  357. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/adapters/claude.py +0 -0
  358. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/adapters/gemini.py +0 -0
  359. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/commands/__init__.py +0 -0
  360. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/commands/skills.py +0 -0
  361. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/parser.py +0 -0
  362. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/provider.py +0 -0
  363. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/stubs/.ai/fastapi-startkit/database/SKILL.md +0 -0
  364. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/__init__.py +0 -0
  365. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/config/__init__.py +0 -0
  366. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/config/storage.py +0 -0
  367. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/data/mime.types +0 -0
  368. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/drivers/__init__.py +0 -0
  369. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/drivers/fake.py +0 -0
  370. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/drivers/local.py +0 -0
  371. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/drivers/s3.py +0 -0
  372. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/file.py +0 -0
  373. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/filestream.py +0 -0
  374. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/helper.py +0 -0
  375. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/providers/provider.py +0 -0
  376. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/storage.py +0 -0
  377. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/support/__init__.py +0 -0
  378. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/support/collection.py +0 -0
  379. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/support/string.py +0 -0
  380. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/support/uri.py +0 -0
  381. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/testing/__init__.py +0 -0
  382. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/testing/test_case.py +0 -0
  383. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/utils/structures.py +0 -0
  384. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/__init__.py +0 -0
  385. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/config/vite.py +0 -0
  386. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/exceptions.py +0 -0
  387. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/providers/provider.py +0 -0
  388. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/stubs/package.json +0 -0
  389. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/stubs/resources/css/app.css +0 -0
  390. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/stubs/resources/js/app.ts +0 -0
  391. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/stubs/templates/index.html +0 -0
  392. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/stubs/tsconfig.json +0 -0
  393. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/stubs/vite.config.ts +0 -0
  394. {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.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.44.0
3
+ Version: 0.45.0
4
4
  Summary: Fastapi Starter kit components
5
5
  Author: Bedram Tamang
6
6
  Author-email: Bedram Tamang <tmgbedu@gmail.com>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fastapi-startkit"
3
- version = "0.44.0"
3
+ version = "0.45.0"
4
4
  description = "Fastapi Starter kit components"
5
5
  authors = [
6
6
  {name = "Bedram Tamang", email = "tmgbedu@gmail.com"}
@@ -0,0 +1,8 @@
1
+ from fastapi_startkit.fastapi.testing.assertable_json import (
2
+ AssertableJson,
3
+ assert_json_structure,
4
+ )
5
+ from fastapi_startkit.fastapi.testing.test_case import HttpTestCase
6
+ from fastapi_startkit.fastapi.testing.test_response import TestResponse
7
+
8
+ __all__ = ["HttpTestCase", "TestResponse", "AssertableJson", "assert_json_structure"]
@@ -0,0 +1,332 @@
1
+ """Fluent JSON assertions for HTTP tests.
2
+
3
+ Provides :class:`AssertableJson`, a chainable wrapper around a decoded JSON
4
+ body (``dict``/``list``).
5
+
6
+ Example::
7
+
8
+ response.assert_json(lambda json: (
9
+ json.where("id", 1)
10
+ .where("name", "Bedu")
11
+ .where("active", lambda v: v is True)
12
+ .has("profile", lambda profile: (
13
+ profile.where("email", "a@b.com").etc()
14
+ ))
15
+ .etc()
16
+ ))
17
+
18
+ Every ``where``/``has`` call records an interaction with the touched key.
19
+ When an assertion scope closes, :meth:`AssertableJson._verify` asserts that
20
+ every property of an object was interacted with — unless :meth:`etc` was
21
+ called to acknowledge the remaining keys. This catches unexpected or extra
22
+ keys in responses.
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ from typing import Any, Callable, Union
28
+
29
+ # A sentinel distinguishing "argument not provided" from an explicit ``None``.
30
+ _MISSING = object()
31
+
32
+ # Mapping of friendly type names to the Python types that satisfy them.
33
+ # ``bool`` is intentionally excluded from the numeric types because in Python
34
+ # ``bool`` is a subclass of ``int`` and JSON keeps the two concepts distinct.
35
+ _JSON_TYPES: dict[str, Callable[[Any], bool]] = {
36
+ "string": lambda v: isinstance(v, str),
37
+ "integer": lambda v: isinstance(v, int) and not isinstance(v, bool),
38
+ "double": lambda v: isinstance(v, float),
39
+ "number": lambda v: isinstance(v, (int, float)) and not isinstance(v, bool),
40
+ "boolean": lambda v: isinstance(v, bool),
41
+ "array": lambda v: isinstance(v, list),
42
+ "object": lambda v: isinstance(v, dict),
43
+ "null": lambda v: v is None,
44
+ }
45
+
46
+
47
+ class AssertableJson:
48
+ """A chainable, scope-aware assertion helper for decoded JSON bodies."""
49
+
50
+ def __init__(self, data: Any, path: str = "") -> None:
51
+ self._data = data
52
+ self._path = path
53
+ self._interacted: set[str] = set()
54
+
55
+ # ------------------------------------------------------------------ #
56
+ # Internal helpers
57
+ # ------------------------------------------------------------------ #
58
+ def _full(self, key: Any) -> str:
59
+ """Return the absolute dot-path to ``key`` for error messages."""
60
+ return f"{self._path}.{key}" if self._path else str(key)
61
+
62
+ @staticmethod
63
+ def _step(node: Any, seg: str) -> tuple[bool, Any]:
64
+ """Descend one segment into a dict key or a list index."""
65
+ if isinstance(node, dict) and seg in node:
66
+ return True, node[seg]
67
+ if isinstance(node, list) and seg.lstrip("-").isdigit():
68
+ index = int(seg)
69
+ if -len(node) <= index < len(node):
70
+ return True, node[index]
71
+ return False, None
72
+
73
+ def _exists(self, key: Any) -> bool:
74
+ node = self._data
75
+ for seg in str(key).split("."):
76
+ found, node = self._step(node, seg)
77
+ if not found:
78
+ return False
79
+ return True
80
+
81
+ def _get(self, key: Any) -> Any:
82
+ """Resolve a (possibly dotted) ``key`` or raise with the full path."""
83
+ node = self._data
84
+ for seg in str(key).split("."):
85
+ found, node = self._step(node, seg)
86
+ assert found, f"Property [{self._full(key)}] does not exist."
87
+ return node
88
+
89
+ def _record(self, key: Any) -> None:
90
+ """Track that the top-level segment of ``key`` was interacted with."""
91
+ self._interacted.add(str(key).split(".")[0])
92
+
93
+ # ------------------------------------------------------------------ #
94
+ # Matching — where family
95
+ # ------------------------------------------------------------------ #
96
+ def where(self, key: str, expected: Union[Any, Callable[[Any], bool]]) -> "AssertableJson":
97
+ """Assert that ``key`` matches ``expected``.
98
+
99
+ ``expected`` may be a literal value, or a callable predicate that
100
+ receives the actual value and returns a truthy result.
101
+ """
102
+ self._record(key)
103
+ actual = self._get(key)
104
+ if callable(expected):
105
+ assert expected(actual), f"Property [{self._full(key)}] was unexpected value [{actual!r}]."
106
+ else:
107
+ assert actual == expected, (
108
+ f"Property [{self._full(key)}] does not match. Expected [{expected!r}], got [{actual!r}]."
109
+ )
110
+ return self
111
+
112
+ def where_not(self, key: str, expected: Union[Any, Callable[[Any], bool]]) -> "AssertableJson":
113
+ """Assert that ``key`` does NOT match ``expected`` (value or predicate)."""
114
+ self._record(key)
115
+ actual = self._get(key)
116
+ if callable(expected):
117
+ assert not expected(actual), (
118
+ f"Property [{self._full(key)}] was not expected to pass the "
119
+ f"given predicate but did (value [{actual!r}])."
120
+ )
121
+ else:
122
+ assert actual != expected, f"Property [{self._full(key)}] was not expected to equal [{expected!r}] but did."
123
+ return self
124
+
125
+ def where_all(self, bindings: dict) -> "AssertableJson":
126
+ """Assert each ``{key: expected}`` pair via :meth:`where`."""
127
+ for key, expected in bindings.items():
128
+ self.where(key, expected)
129
+ return self
130
+
131
+ def where_all_type(self, bindings: dict) -> "AssertableJson":
132
+ """Assert each ``{key: type}`` pair via :meth:`where_type`."""
133
+ for key, expected in bindings.items():
134
+ self.where_type(key, expected)
135
+ return self
136
+
137
+ def where_type(self, key: str, expected: Union[str, list[str]]) -> "AssertableJson":
138
+ """Assert that ``key`` is one of the given JSON type name(s).
139
+
140
+ Accepts a single name (``"string"``), a pipe form (``"string|null"``)
141
+ or a list (``["string", "null"]``). Supported names: string, integer,
142
+ double, number, boolean, array, object, null.
143
+ """
144
+ self._record(key)
145
+ actual = self._get(key)
146
+ if isinstance(expected, str):
147
+ names = expected.split("|")
148
+ else:
149
+ names = list(expected)
150
+ for name in names:
151
+ if name not in _JSON_TYPES:
152
+ raise ValueError(f"Unknown JSON type [{name}] for [{self._full(key)}].")
153
+ assert any(_JSON_TYPES[name](actual) for name in names), (
154
+ f"Property [{self._full(key)}] is not of expected type [{'|'.join(names)}]; got value [{actual!r}]."
155
+ )
156
+ return self
157
+
158
+ # ------------------------------------------------------------------ #
159
+ # Presence — has family
160
+ # ------------------------------------------------------------------ #
161
+ def has(
162
+ self,
163
+ key: str,
164
+ length: Any = _MISSING,
165
+ callback: Callable[["AssertableJson"], Any] = _MISSING,
166
+ ) -> "AssertableJson":
167
+ """Assert that ``key`` exists, optionally its length and/or a scope.
168
+
169
+ Supports the shorthands:
170
+
171
+ * ``has("key")`` — just assert presence.
172
+ * ``has("key", 3)`` — assert it is a sized collection of length 3.
173
+ * ``has("key", callback)`` — scope into ``key`` and run nested asserts.
174
+ * ``has("key", 3, callback)`` — both length and a nested scope.
175
+ """
176
+ self._record(key)
177
+ value = self._get(key)
178
+
179
+ # ``has("key", callback)`` shorthand: length slot holds the callback.
180
+ if callable(length):
181
+ callback = length
182
+ length = _MISSING
183
+
184
+ if length is not _MISSING:
185
+ assert isinstance(value, (list, dict, str)), f"Property [{self._full(key)}] is not countable."
186
+ assert len(value) == length, (
187
+ f"Property [{self._full(key)}] does not have the expected size. "
188
+ f"Expected [{length}], got [{len(value)}]."
189
+ )
190
+
191
+ if callback is not _MISSING:
192
+ child = AssertableJson(value, self._full(key))
193
+ callback(child)
194
+ child._verify()
195
+
196
+ return self
197
+
198
+ def has_all(self, *keys: str) -> "AssertableJson":
199
+ """Assert that every key in ``keys`` exists. Accepts a list or varargs."""
200
+ for key in self._flatten(keys):
201
+ assert self._exists(key), f"Property [{self._full(key)}] does not exist."
202
+ self._record(key)
203
+ return self
204
+
205
+ def has_any(self, *keys: str) -> "AssertableJson":
206
+ """Assert that at least one key in ``keys`` exists."""
207
+ keys = self._flatten(keys)
208
+ for key in keys:
209
+ self._record(key)
210
+ assert any(self._exists(key) for key in keys), (
211
+ f"None of the expected properties [{', '.join(map(self._full, keys))}] exist."
212
+ )
213
+ return self
214
+
215
+ def missing(self, key: str) -> "AssertableJson":
216
+ """Assert that ``key`` is absent from the current scope."""
217
+ assert not self._exists(key), f"Property [{self._full(key)}] was expected to be missing but exists."
218
+ return self
219
+
220
+ def missing_all(self, *keys: str) -> "AssertableJson":
221
+ """Assert that none of ``keys`` exist."""
222
+ for key in self._flatten(keys):
223
+ self.missing(key)
224
+ return self
225
+
226
+ def count(self, key: str, length: int) -> "AssertableJson":
227
+ """Assert that the collection at ``key`` has exactly ``length`` items."""
228
+ return self.has(key, length)
229
+
230
+ @staticmethod
231
+ def _flatten(keys: tuple) -> tuple:
232
+ """Allow both ``has_all("a", "b")`` and ``has_all(["a", "b"])``."""
233
+ if len(keys) == 1 and isinstance(keys[0], (list, tuple)):
234
+ return tuple(keys[0])
235
+ return keys
236
+
237
+ # ------------------------------------------------------------------ #
238
+ # Traversal — first / each
239
+ # ------------------------------------------------------------------ #
240
+ def first(self, callback: Callable[["AssertableJson"], Any]) -> "AssertableJson":
241
+ """Scope into the first child element and run ``callback`` against it."""
242
+ assert self._data, f"Cannot scope into the first element of empty [{self._path or 'root'}]."
243
+ if isinstance(self._data, list):
244
+ key, value = 0, self._data[0]
245
+ else:
246
+ key, value = next(iter(self._data.items()))
247
+ child = AssertableJson(value, self._full(key))
248
+ callback(child)
249
+ child._verify()
250
+ self._record(key)
251
+ return self
252
+
253
+ def each(self, callback: Callable[["AssertableJson"], Any]) -> "AssertableJson":
254
+ """Run ``callback`` against every child element in its own scope."""
255
+ if isinstance(self._data, list):
256
+ items = list(enumerate(self._data))
257
+ elif isinstance(self._data, dict):
258
+ items = list(self._data.items())
259
+ else:
260
+ raise AssertionError(f"Property [{self._path or 'root'}] is not iterable for each().")
261
+ for key, value in items:
262
+ child = AssertableJson(value, self._full(key))
263
+ callback(child)
264
+ child._verify()
265
+ self._record(key)
266
+ return self
267
+
268
+ # ------------------------------------------------------------------ #
269
+ # Interaction control
270
+ # ------------------------------------------------------------------ #
271
+ def etc(self) -> "AssertableJson":
272
+ """Acknowledge any remaining, un-asserted keys in this scope."""
273
+ if isinstance(self._data, dict):
274
+ self._interacted.update(self._data.keys())
275
+ return self
276
+
277
+ def _verify(self) -> None:
278
+ """Assert every object property was interacted with (or ``etc``'d)."""
279
+ if isinstance(self._data, dict):
280
+ extra = set(self._data.keys()) - self._interacted
281
+ assert not extra, (
282
+ f"Unexpected properties were found at [{self._path or 'root'}]: "
283
+ f"{sorted(extra)}. Interact with them or call .etc()."
284
+ )
285
+
286
+ # ------------------------------------------------------------------ #
287
+ # Phase-2 / TODO — explicit stubs.
288
+ # ------------------------------------------------------------------ #
289
+ def where_contains(self, key: str, expected: Any) -> "AssertableJson": # pragma: no cover
290
+ """TODO(phase-2): assert the collection at ``key`` contains ``expected``."""
291
+ raise NotImplementedError("where_contains is planned for phase 2.")
292
+
293
+ def count_between(self, key: str, minimum: int, maximum: int) -> "AssertableJson": # pragma: no cover
294
+ """TODO(phase-2): assert the size of ``key`` is within [min, max]."""
295
+ raise NotImplementedError("count_between is planned for phase 2.")
296
+
297
+
298
+ def assert_json_structure(structure: Any, data: Any, path: str = "root") -> None:
299
+ """Assert that ``data`` contains the keys described by ``structure``.
300
+
301
+ ``structure`` may be:
302
+
303
+ * a list of leaf key names, e.g. ``["name", "sport"]`` — each must exist
304
+ on the object ``data``;
305
+ * a dict mapping a key to a nested structure, e.g.
306
+ ``{"teams": ["name", "sport"]}``;
307
+ * a ``"*"`` key whose value is applied to every element of a list, e.g.
308
+ ``{"teams": {"*": ["name", "sport"]}}``.
309
+
310
+ A leaf may map to ``None`` in dict form to assert presence only.
311
+ """
312
+ if isinstance(structure, list):
313
+ for value in structure:
314
+ if isinstance(value, (list, dict)):
315
+ assert_json_structure(value, data, path)
316
+ else:
317
+ assert isinstance(data, dict) and value in data, f"Missing key [{value}] at [{path}]."
318
+ return
319
+
320
+ if isinstance(structure, dict):
321
+ for key, value in structure.items():
322
+ if key == "*":
323
+ assert isinstance(data, list), f"Expected a list at [{path}]."
324
+ for index, item in enumerate(data):
325
+ assert_json_structure(value, item, f"{path}.{index}")
326
+ else:
327
+ assert isinstance(data, dict) and key in data, f"Missing key [{key}] at [{path}]."
328
+ if value is not None:
329
+ assert_json_structure(value, data[key], f"{path}.{key}")
330
+ return
331
+
332
+ raise TypeError(f"Invalid structure node at [{path}]: {structure!r}")
@@ -0,0 +1,35 @@
1
+ from abc import ABC
2
+
3
+ from fastapi_startkit.fastapi.testing.test_response import TestResponse
4
+ from fastapi_startkit.testing import TestCase
5
+ from httpx import AsyncClient, ASGITransport
6
+
7
+
8
+ class HttpTestCase(TestCase, ABC):
9
+ client: AsyncClient
10
+
11
+ async def asyncSetUp(self):
12
+ await super().asyncSetUp()
13
+ self._client_ctx = AsyncClient(
14
+ transport=ASGITransport(app=self.get_application().fastapi), base_url="http://test"
15
+ )
16
+ self.client = await self._client_ctx.__aenter__()
17
+
18
+ async def asyncTearDown(self):
19
+ await self._client_ctx.__aexit__(None, None, None)
20
+ await super().asyncTearDown()
21
+
22
+ async def get(self, url, **kwargs) -> TestResponse:
23
+ return TestResponse(await self.client.get(url, **kwargs))
24
+
25
+ async def post(self, url, **kwargs) -> TestResponse:
26
+ return TestResponse(await self.client.post(url, **kwargs))
27
+
28
+ async def put(self, url, **kwargs) -> TestResponse:
29
+ return TestResponse(await self.client.put(url, **kwargs))
30
+
31
+ async def patch(self, url, **kwargs) -> TestResponse:
32
+ return TestResponse(await self.client.patch(url, **kwargs))
33
+
34
+ async def delete(self, url, **kwargs) -> TestResponse:
35
+ return TestResponse(await self.client.delete(url, **kwargs))
@@ -0,0 +1,102 @@
1
+ """A thin, chainable wrapper around ``httpx.Response`` for HTTP tests.
2
+
3
+ :class:`TestResponse` adds assertion helpers
4
+ (``assert_status``, ``assert_ok``, ``assert_json``) while transparently
5
+ delegating every other attribute/method to the underlying ``httpx.Response``
6
+ via ``__getattr__``. Existing tests that read ``response.status_code`` or call
7
+ ``response.json()`` continue to work unchanged.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from typing import Any, Callable, Optional
13
+
14
+ from httpx import Response
15
+
16
+ from fastapi_startkit.fastapi.testing.assertable_json import (
17
+ AssertableJson,
18
+ assert_json_structure,
19
+ )
20
+
21
+
22
+ class TestResponse:
23
+ """Wraps an ``httpx.Response`` and adds fluent assertion helpers."""
24
+
25
+ # Prevent pytest from trying to collect this as a test class.
26
+ __test__ = False
27
+
28
+ def __init__(self, response: Response) -> None:
29
+ self._response = response
30
+
31
+ @property
32
+ def response(self) -> Response:
33
+ """Access the underlying ``httpx.Response`` directly."""
34
+ return self._response
35
+
36
+ def __getattr__(self, name: str) -> Any:
37
+ # Only called when ``name`` is not found on this wrapper, so this
38
+ # transparently forwards status_code, headers, json(), text, etc.
39
+ return getattr(self._response, name)
40
+
41
+ def __repr__(self) -> str: # pragma: no cover - cosmetic
42
+ return f"<TestResponse {self._response.status_code} {self._response.url}>"
43
+
44
+ # ------------------------------------------------------------------ #
45
+ # Status assertions
46
+ # ------------------------------------------------------------------ #
47
+ def assert_status(self, code: int) -> "TestResponse":
48
+ """Assert the response has the given HTTP status code."""
49
+ actual = self._response.status_code
50
+ assert actual == code, f"Expected status code [{code}] but received [{actual}]. Body: {self._response.text}"
51
+ return self
52
+
53
+ def assert_ok(self) -> "TestResponse":
54
+ """Assert the response status code is 200 OK."""
55
+ return self.assert_status(200)
56
+
57
+ def assert_created(self) -> "TestResponse":
58
+ """Assert the response status code is 201 Created."""
59
+ return self.assert_status(201)
60
+
61
+ def assert_no_content(self) -> "TestResponse":
62
+ """Assert the response status code is 204 No Content."""
63
+ return self.assert_status(204)
64
+
65
+ # ------------------------------------------------------------------ #
66
+ # JSON assertions
67
+ # ------------------------------------------------------------------ #
68
+ def assert_json(
69
+ self,
70
+ callback: Optional[Callable[[AssertableJson], Any]] = None,
71
+ *,
72
+ exact: Any = None,
73
+ ) -> "TestResponse":
74
+ """Assert against the JSON body.
75
+
76
+ * ``assert_json(lambda j: j.where(...))`` — run fluent assertions; the
77
+ strict interaction model is enforced (unexpected keys fail unless
78
+ ``etc()`` is called).
79
+ * ``assert_json(exact={...})`` — assert the decoded body equals
80
+ ``exact`` exactly.
81
+ """
82
+ body = self._response.json()
83
+ if callback is not None:
84
+ fluent = AssertableJson(body)
85
+ callback(fluent)
86
+ fluent._verify()
87
+ if exact is not None:
88
+ assert body == exact, f"JSON body does not match exactly.\nExpected: {exact!r}\nActual: {body!r}"
89
+ return self
90
+
91
+ def assert_json_structure(self, structure: Any) -> "TestResponse":
92
+ """Assert the JSON body has the given key structure.
93
+
94
+ Use a ``"*"`` key to apply a nested structure to every element of a
95
+ list::
96
+
97
+ response.assert_json_structure({
98
+ "teams": {"*": ["name", "sport"]},
99
+ })
100
+ """
101
+ assert_json_structure(structure, self._response.json())
102
+ return self
@@ -316,6 +316,10 @@ class Model(Attribute, Relationship, ObservesEvents):
316
316
 
317
317
  return instance
318
318
 
319
+ @classmethod
320
+ async def insert(cls, values: dict | list) -> int | None:
321
+ return await cls.query().insert(values)
322
+
319
323
  async def update(self, attributes: dict) -> bool:
320
324
  if not self._exists:
321
325
  return False
@@ -50,6 +50,12 @@ class PostgresGrammar(BaseGrammar):
50
50
  def delete_format(self):
51
51
  return "DELETE FROM {table} {wheres}"
52
52
 
53
+ def insert_format(self):
54
+ return "INSERT INTO {table} ({columns}) VALUES ({values})"
55
+
56
+ def bulk_insert_format(self):
57
+ return "INSERT INTO {table} ({columns}) VALUES {values}"
58
+
53
59
  def aggregate_string_with_alias(self):
54
60
  return "{aggregate_function}({column}) AS {alias}"
55
61
 
@@ -35,6 +35,9 @@ class SkillRegistry:
35
35
  "database": [
36
36
  ".ai/fastapi-startkit/database/SKILL.md",
37
37
  ],
38
+ "inertia": [
39
+ ".ai/fastapi-startkit/inertia/SKILL.md",
40
+ ],
38
41
  }
39
42
 
40
43
  def __init__(self, app: "Application") -> None:
@@ -0,0 +1,149 @@
1
+ ---
2
+ name: fastapi-startkit
3
+ description: Routing, controllers, ORM, requests, resources, and action pattern for fastapi-startkit applications.
4
+ ---
5
+
6
+ # Fastapi's Routing
7
+
8
+ ### Fastapi Startkit's Router
9
+ ```python
10
+ # routes/web.py
11
+ from fastapi_startkit.fastapi import Router
12
+
13
+ router = Router()
14
+ ```
15
+
16
+ and register routes explicitly, for example
17
+ ```python
18
+ router.get("/users", users_controller.index)
19
+ router.post("/users", users_controller.store)
20
+ router.get("/users/{user_id}", users_controller.show)
21
+ router.put("/users/{user_id}", users_controller.update)
22
+ router.patch("/users/{user_id}", users_controller.update)
23
+ router.delete("/users/{user_id}", users_controller.destroy)
24
+ ```
25
+
26
+ ### Resourceful controllers
27
+
28
+ Prefer `router.resource()` to register the seven standard CRUD routes in one
29
+ call. It maps to a **resourceful controller** with these methods:
30
+
31
+ | Method | Verb & URI | Purpose |
32
+ |-----------|-----------------------------|----------------------------------|
33
+ | `index` | GET `/users` | List the collection |
34
+ | `create` | GET `/users/create` | Show the "new" form |
35
+ | `store` | POST `/users` | Persist a new record |
36
+ | `show` | GET `/users/{user}` | Show a single record |
37
+ | `edit` | GET `/users/{user}/edit` | Show the "edit" form |
38
+ | `update` | PUT/PATCH `/users/{user}` | Persist changes to a record |
39
+ | `destroy` | DELETE `/users/{user}` | Delete a record |
40
+
41
+ ```python
42
+ # routes/web.py
43
+ router.resource("users", users_controller)
44
+
45
+ # subset / exclusions
46
+ router.resource("users", users_controller, only=['index', 'show'])
47
+ router.resource("users", users_controller, excepts=['create', 'edit'])
48
+ ```
49
+
50
+ A full resourceful controller mirrors those seven methods exactly:
51
+ ```python
52
+ # app/http/controllers/users_controller.py
53
+ from fastapi_startkit.jsonapi import JsonResource
54
+
55
+ from app.models import User
56
+ from app.http.requests.user_store_request import UserStoreRequest
57
+
58
+ async def index():
59
+ users = await User.all()
60
+ return JsonResource.collection(users)
61
+
62
+ async def create():
63
+ # render/return the "create" form payload
64
+ ...
65
+
66
+ async def store(request: UserStoreRequest):
67
+ user = await User.create(request.model_dump())
68
+ return JsonResource(user)
69
+
70
+ async def show(user: int):
71
+ return JsonResource(await User.find_or_fail(user))
72
+
73
+ async def edit(user: int):
74
+ # render/return the "edit" form payload for the record
75
+ return JsonResource(await User.find_or_fail(user))
76
+
77
+ async def update(user: int, request: UserStoreRequest):
78
+ record = await User.find_or_fail(user)
79
+ await record.update(request.model_dump())
80
+ return JsonResource(record)
81
+
82
+ async def destroy(user: int):
83
+ record = await User.find_or_fail(user)
84
+ await record.delete()
85
+ return JsonResource(record)
86
+ ```
87
+
88
+ ## ORM
89
+ ```python
90
+ # app/models/user.py
91
+ from fastapi_startkit.masoniteorm import Model
92
+
93
+ class User(Model):
94
+ id: int
95
+ name: str
96
+ email: str
97
+ metadata: dict
98
+ ```
99
+
100
+ and use the orm as:
101
+ ```python
102
+ # app/http/controllers/users_controller.py
103
+ from app.models import User
104
+
105
+ async def store(request: UserStoreRequest):
106
+ user = User.create(request.model_dump())
107
+ ...
108
+ ```
109
+
110
+ the `UserStoreRequest` will look like:
111
+ ```python
112
+ # app/http/requests/user_store_request.py
113
+ from pydantic import BaseModel
114
+
115
+ class UserStoreRequest(BaseModel):
116
+ name: str
117
+ ```
118
+
119
+ and use JsonApiResource to return JSON response from the controller:
120
+ ```python
121
+ from fastapi_startkit.jsonapi import JsonResource
122
+
123
+ # app/http/controllers/users_controller.py
124
+ from app.models import User
125
+
126
+ async def store(request: UserStoreRequest):
127
+ user = User.create(request.model_dump())
128
+ return JsonResource(user)
129
+ ```
130
+
131
+ ## Architecture
132
+
133
+ use the action pattern to write complex logic.
134
+ ```python
135
+ # app/actions/user_actions.py
136
+ from app.models import User
137
+
138
+ class UserStoreAction:
139
+ def __init__(self, request: UserStoreRequest):
140
+ self.request = request
141
+
142
+ @staticmethod
143
+ def prepare(request: UserStoreRequest) -> 'UserStoreAction':
144
+ return UserStoreAction(request)
145
+
146
+ def handle(self) -> JsonResource[User]:
147
+ user = User.create(self.request.model_dump())
148
+ return JsonResource(user)
149
+ ```