fastapi-admin-kit 0.1.0__tar.gz → 0.1.2__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 (170) hide show
  1. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/.gitignore +1 -0
  2. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/PKG-INFO +11 -8
  3. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/README.md +8 -5
  4. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/__init__.py +4 -1
  5. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/admin/admin_database.py +12 -3
  6. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/admin/core.py +9 -2
  7. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/api/roles.py +1 -1
  8. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/api/search.py +3 -2
  9. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/auth/csrf.py +4 -3
  10. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/auth/views.py +6 -3
  11. fastapi_admin_kit-0.1.2/fastapi_admin_kit/cli/__init__.py +79 -0
  12. fastapi_admin_kit-0.1.2/fastapi_admin_kit/cli/__main__.py +5 -0
  13. fastapi_admin_kit-0.1.2/fastapi_admin_kit/cli/scaffold.py +287 -0
  14. fastapi_admin_kit-0.1.0/fastapi_admin_kit/cli.py → fastapi_admin_kit-0.1.2/fastapi_admin_kit/cli/user.py +8 -21
  15. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/config/__init__.py +3 -0
  16. fastapi_admin_kit-0.1.2/fastapi_admin_kit/config/database.py +150 -0
  17. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/form/pipeline.py +20 -3
  18. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/inspection/__init__.py +28 -0
  19. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/modeladmin.py +26 -0
  20. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/router.py +196 -2
  21. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/static/css/admin.css +64 -0
  22. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/static/js/admin.js +13 -1
  23. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/base.html +3 -0
  24. fastapi_admin_kit-0.1.2/fastapi_admin_kit/templates/partials/_inline_edit_row.html +85 -0
  25. fastapi_admin_kit-0.1.2/fastapi_admin_kit/templates/partials/inline_edit_form.html +32 -0
  26. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/partials/list_table.html +9 -6
  27. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/class_views.py +4 -2
  28. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/factory.py +8 -4
  29. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/profile.py +8 -2
  30. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/renderers.py +2 -1
  31. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/roles.py +60 -31
  32. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/totp.py +4 -1
  33. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/mkdocs.yml +3 -0
  34. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/pyproject.toml +4 -3
  35. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/LICENSE +0 -0
  36. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/actions/__init__.py +0 -0
  37. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/actions/base.py +0 -0
  38. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/actions/registry.py +0 -0
  39. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/admin/__init__.py +0 -0
  40. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/admin/admin_config.py +0 -0
  41. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/admin/admin_router.py +0 -0
  42. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/admin/admin_template.py +0 -0
  43. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/admin/builtin_models.py +0 -0
  44. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/admin/decorators.py +0 -0
  45. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/admin/state.py +0 -0
  46. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/admin.py +0 -0
  47. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/api/__init__.py +0 -0
  48. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/api/auth.py +0 -0
  49. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/api/crud.py +0 -0
  50. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/api/deps.py +0 -0
  51. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/api/schema_generator.py +0 -0
  52. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/api/schemas.py +0 -0
  53. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/audit/__init__.py +0 -0
  54. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/audit/context.py +0 -0
  55. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/audit/diff.py +0 -0
  56. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/audit/event_bus.py +0 -0
  57. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/audit/events.py +0 -0
  58. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/audit/listener.py +0 -0
  59. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/audit/logger.py +0 -0
  60. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/audit/middleware.py +0 -0
  61. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/audit/models.py +0 -0
  62. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/audit/sqlalchemy_logger.py +0 -0
  63. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/auth/__init__.py +0 -0
  64. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/auth/backend.py +0 -0
  65. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/auth/dependencies.py +0 -0
  66. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/auth/identity.py +0 -0
  67. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/auth/models.py +0 -0
  68. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/auth/password.py +0 -0
  69. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/auth/permissions.py +0 -0
  70. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/auth/protocol.py +0 -0
  71. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/auth/ratelimit.py +0 -0
  72. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/auth/router.py +0 -0
  73. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/auth/session.py +0 -0
  74. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/auth/totp.py +0 -0
  75. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/config/audit.py +0 -0
  76. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/config/auth.py +0 -0
  77. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/config/behavior.py +0 -0
  78. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/config/nav.py +0 -0
  79. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/config/storage.py +0 -0
  80. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/config/theme.py +0 -0
  81. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/config/ui.py +0 -0
  82. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/dashboard/__init__.py +0 -0
  83. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/db.py +0 -0
  84. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/exceptions.py +0 -0
  85. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/field_types.py +0 -0
  86. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/filters/__init__.py +0 -0
  87. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/filters/base.py +0 -0
  88. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/filters/registry.py +0 -0
  89. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/flash.py +0 -0
  90. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/form/__init__.py +0 -0
  91. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/inspection/registry.py +0 -0
  92. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/inspection.py +0 -0
  93. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/models/__init__.py +0 -0
  94. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/models/base.py +0 -0
  95. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/nav.py +0 -0
  96. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/pagination/__init__.py +0 -0
  97. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/pagination/base.py +0 -0
  98. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/pagination/cursor.py +0 -0
  99. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/pagination/dynamic.py +0 -0
  100. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/pagination/offset.py +0 -0
  101. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/plugins/__init__.py +0 -0
  102. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/py.typed +0 -0
  103. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/registry/__init__.py +0 -0
  104. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/registry/core.py +0 -0
  105. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/registry/validation.py +0 -0
  106. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/registry.py +0 -0
  107. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/static/css/presets.css +0 -0
  108. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/static/css/tokens.css +0 -0
  109. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/static/css/variables.css +0 -0
  110. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/static/icons/heroicons.svg +0 -0
  111. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/static/js/htmx-config.js +0 -0
  112. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/storage/__init__.py +0 -0
  113. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/storage/base.py +0 -0
  114. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/storage/local.py +0 -0
  115. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/macros/form_fields.html +0 -0
  116. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/macros/icons.html +0 -0
  117. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/macros/table.html +0 -0
  118. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/macros/widgets.html +0 -0
  119. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/2fa/setup.html +0 -0
  120. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/2fa/verify.html +0 -0
  121. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/audit_detail.html +0 -0
  122. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/audit_log.html +0 -0
  123. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/dashboard.html +0 -0
  124. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/detail.html +0 -0
  125. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/form.html +0 -0
  126. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/list.html +0 -0
  127. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/login.html +0 -0
  128. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/profile/password.html +0 -0
  129. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/profile/profile.html +0 -0
  130. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/role_form.html +0 -0
  131. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/roles/form.html +0 -0
  132. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/roles/list.html +0 -0
  133. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/roles.html +0 -0
  134. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/settings/theme.html +0 -0
  135. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/users/form.html +0 -0
  136. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/pages/users/list.html +0 -0
  137. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/partials/command_palette.html +0 -0
  138. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/partials/field_wrapper.html +0 -0
  139. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/partials/flash_messages.html +0 -0
  140. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/partials/head.html +0 -0
  141. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/partials/head_minimal.html +0 -0
  142. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/partials/mobile_backdrop.html +0 -0
  143. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/partials/pagination.html +0 -0
  144. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/partials/permission_widget.html +0 -0
  145. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/partials/scripts.html +0 -0
  146. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/partials/sidebar.html +0 -0
  147. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/templates/partials/topbar.html +0 -0
  148. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/types.py +0 -0
  149. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/validation.py +0 -0
  150. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/__init__.py +0 -0
  151. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/audit.py +0 -0
  152. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/bulk.py +0 -0
  153. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/context.py +0 -0
  154. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/dashboard.py +0 -0
  155. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/delete.py +0 -0
  156. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/extra.py +0 -0
  157. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/form.py +0 -0
  158. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/list.py +0 -0
  159. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/protocols.py +0 -0
  160. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/search.py +0 -0
  161. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/settings.py +0 -0
  162. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/sidebar.py +0 -0
  163. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views/users.py +0 -0
  164. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/views.py +0 -0
  165. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/widgets/__init__.py +0 -0
  166. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/widgets/base.py +0 -0
  167. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/widgets/inputs.py +0 -0
  168. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/widgets/registry.py +0 -0
  169. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/widgets/relation.py +0 -0
  170. {fastapi_admin_kit-0.1.0 → fastapi_admin_kit-0.1.2}/fastapi_admin_kit/widgets/resolver.py +0 -0
@@ -28,6 +28,7 @@ pip-delete-this-directory.txt
28
28
  # Virtual environments
29
29
  .venv/
30
30
  venv/
31
+ list/
31
32
  ENV/
32
33
  env/
33
34
  .env
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-admin-kit
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: Drop-in admin panel for FastAPI + SQLAlchemy + SQLModel apps
5
5
  Project-URL: Homepage, https://github.com/borhanst/fastapi-admin-kit
6
6
  Project-URL: Documentation, https://borhanst.github.io/fastapi-admin-kit/
@@ -25,13 +25,13 @@ Classifier: Typing :: Typed
25
25
  Requires-Python: >=3.11
26
26
  Requires-Dist: aiosqlite>=0.20.0
27
27
  Requires-Dist: bcrypt>=4.0.0
28
- Requires-Dist: fastapi>=0.136.3
28
+ Requires-Dist: fastapi>=0.115.0
29
29
  Requires-Dist: itsdangerous>=2.2.0
30
30
  Requires-Dist: jinja2>=3.1.0
31
31
  Requires-Dist: pyjwt>=2.13.0
32
32
  Requires-Dist: python-multipart>=0.0.9
33
33
  Requires-Dist: sqlalchemy>=2.0.0
34
- Requires-Dist: uvicorn>=0.49.0
34
+ Requires-Dist: uvicorn>=0.30.0
35
35
  Provides-Extra: dev
36
36
  Requires-Dist: hatch>=1.13.0; extra == 'dev'
37
37
  Requires-Dist: httpx>=0.27.0; extra == 'dev'
@@ -58,6 +58,8 @@ Description-Content-Type: text/markdown
58
58
 
59
59
  A drop-in admin panel for FastAPI + SQLAlchemy apps, inspired by Django Unfold.
60
60
 
61
+ > **⚠️ Important Notice:** This project is **not production-ready yet**. It is under active development, and the API and code may massive changes. Use it for development and testing purposes only.
62
+
61
63
  📖 **[Documentation](https://borhanst.github.io/fastapi-admin-kit/)** | 🚀 **[Quick Start](#quick-start)** | 📦 **[PyPI](https://pypi.org/project/fastapi-admin-kit/)**
62
64
 
63
65
  ## Features
@@ -66,7 +68,8 @@ A drop-in admin panel for FastAPI + SQLAlchemy apps, inspired by Django Unfold.
66
68
  - Built-in authentication, RBAC, and audit logging
67
69
  - Modern UI with Tailwind CSS, HTMX, and Alpine.js
68
70
  - Fully customizable widgets, themes, and templates
69
- - CLI for user management (`fastapi-admin-kit` / `fak` create superusers, list users, change passwords)
71
+ - Inline editing from list view with 3-dot action menu
72
+ - CLI for user management (`fak-admin` / `fak` — create superusers, list users, change passwords)
70
73
  - Async-first with support for PostgreSQL, MySQL, and SQLite
71
74
 
72
75
  ## Installation
@@ -138,15 +141,15 @@ Both the full name and the short alias work interchangeably:
138
141
 
139
142
  ```bash
140
143
  # Create a superuser
141
- fastapi-admin-kit create-superuser -e admin@example.com -p mypassword
142
- fak create-superuser -e admin@example.com -p mypassword # short alias
144
+ fak-admin createsuperuser -e admin@example.com -p mypassword
145
+ fak createsuperuser -e admin@example.com -p mypassword # short alias
143
146
 
144
147
  # List all admin users
145
- fastapi-admin-kit users
148
+ fak-admin users
146
149
  fak users
147
150
 
148
151
  # Change a user's password
149
- fastapi-admin-kit changepassword -e admin@example.com -p newpassword
152
+ fak-admin changepassword -e admin@example.com -p newpassword
150
153
  fak changepassword -e admin@example.com -p newpassword
151
154
  ```
152
155
 
@@ -6,6 +6,8 @@
6
6
 
7
7
  A drop-in admin panel for FastAPI + SQLAlchemy apps, inspired by Django Unfold.
8
8
 
9
+ > **⚠️ Important Notice:** This project is **not production-ready yet**. It is under active development, and the API and code may massive changes. Use it for development and testing purposes only.
10
+
9
11
  📖 **[Documentation](https://borhanst.github.io/fastapi-admin-kit/)** | 🚀 **[Quick Start](#quick-start)** | 📦 **[PyPI](https://pypi.org/project/fastapi-admin-kit/)**
10
12
 
11
13
  ## Features
@@ -14,7 +16,8 @@ A drop-in admin panel for FastAPI + SQLAlchemy apps, inspired by Django Unfold.
14
16
  - Built-in authentication, RBAC, and audit logging
15
17
  - Modern UI with Tailwind CSS, HTMX, and Alpine.js
16
18
  - Fully customizable widgets, themes, and templates
17
- - CLI for user management (`fastapi-admin-kit` / `fak` create superusers, list users, change passwords)
19
+ - Inline editing from list view with 3-dot action menu
20
+ - CLI for user management (`fak-admin` / `fak` — create superusers, list users, change passwords)
18
21
  - Async-first with support for PostgreSQL, MySQL, and SQLite
19
22
 
20
23
  ## Installation
@@ -86,15 +89,15 @@ Both the full name and the short alias work interchangeably:
86
89
 
87
90
  ```bash
88
91
  # Create a superuser
89
- fastapi-admin-kit create-superuser -e admin@example.com -p mypassword
90
- fak create-superuser -e admin@example.com -p mypassword # short alias
92
+ fak-admin createsuperuser -e admin@example.com -p mypassword
93
+ fak createsuperuser -e admin@example.com -p mypassword # short alias
91
94
 
92
95
  # List all admin users
93
- fastapi-admin-kit users
96
+ fak-admin users
94
97
  fak users
95
98
 
96
99
  # Change a user's password
97
- fastapi-admin-kit changepassword -e admin@example.com -p newpassword
100
+ fak-admin changepassword -e admin@example.com -p newpassword
98
101
  fak changepassword -e admin@example.com -p newpassword
99
102
  ```
100
103
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  from fastapi_admin_kit.admin import Admin
4
4
  from fastapi_admin_kit.admin.decorators import column
5
+ from fastapi_admin_kit.config import DatabaseConfig, DatabaseType
5
6
  from fastapi_admin_kit.exceptions import ConfigError
6
7
  from fastapi_admin_kit.nav import (
7
8
  BuiltNavGroup,
@@ -40,6 +41,8 @@ __all__ = [
40
41
  "Admin",
41
42
  "AdminRegistry",
42
43
  "ConfigError",
44
+ "DatabaseConfig",
45
+ "DatabaseType",
43
46
  "RegisteredModel",
44
47
  "ModelAdmin",
45
48
  "column",
@@ -70,4 +73,4 @@ __all__ = [
70
73
  # Per-model assets
71
74
  "AdminExtra",
72
75
  ]
73
- __version__ = "0.1.0"
76
+ __version__ = "0.1.2"
@@ -1,9 +1,10 @@
1
1
  """Admin database setup and initialization."""
2
2
 
3
- from typing import TYPE_CHECKING, Any
3
+ from __future__ import annotations
4
4
 
5
- if TYPE_CHECKING:
6
- pass
5
+ from typing import Any
6
+
7
+ from fastapi_admin_kit.config.database import DatabaseConfig
7
8
 
8
9
 
9
10
  class AdminDatabase:
@@ -13,9 +14,17 @@ class AdminDatabase:
13
14
  self,
14
15
  engine: Any | None = None,
15
16
  base: Any | None = None,
17
+ database_config: DatabaseConfig | None = None,
16
18
  ):
17
19
  self.engine = engine
18
20
  self.base = base
21
+ self.database_config = database_config
22
+
23
+ def _ensure_engine(self) -> Any:
24
+ """Create the async engine from ``database_config`` if no engine is set."""
25
+ if self.engine is None and self.database_config is not None:
26
+ self.engine = self.database_config.create_engine()
27
+ return self.engine
19
28
 
20
29
  async def _create_tables(self) -> None:
21
30
  """Create all admin database tables (async-safe)."""
@@ -21,6 +21,7 @@ from fastapi_admin_kit.config import (
21
21
  AuditConfig,
22
22
  AuthConfig,
23
23
  BehaviorConfig,
24
+ DatabaseConfig,
24
25
  NavConfig,
25
26
  StorageConfig,
26
27
  ThemeConfig,
@@ -116,6 +117,7 @@ class Admin:
116
117
  self,
117
118
  app: FastAPI | None = None,
118
119
  engine: Engine | None = None,
120
+ database_config: DatabaseConfig | None = None,
119
121
  *,
120
122
  # Component instances (new API)
121
123
  config: AdminConfig | None = None,
@@ -257,7 +259,9 @@ class Admin:
257
259
  )
258
260
 
259
261
  if database is None:
260
- database = AdminDatabase(engine=engine, base=base)
262
+ database = AdminDatabase(
263
+ engine=engine, base=base, database_config=database_config
264
+ )
261
265
 
262
266
  if router is None:
263
267
  router = AdminRouter(
@@ -426,9 +430,12 @@ class Admin:
426
430
  "Admin requires a FastAPI app instance. Pass app= or call setup(app=)."
427
431
  )
428
432
 
433
+ self.database._ensure_engine()
434
+
429
435
  if self.database.engine is None:
430
436
  raise ConfigError(
431
- "Admin requires a SQLAlchemy engine. Pass engine= to Admin()."
437
+ "Admin requires a SQLAlchemy engine. "
438
+ "Pass engine= or database_config= to Admin()."
432
439
  )
433
440
 
434
441
  app = self._app
@@ -106,7 +106,7 @@ async def update_role(
106
106
  )
107
107
 
108
108
 
109
- @router.delete("/{role_id}", status_code=204)
109
+ @router.delete("/{role_id}", status_code=204, response_model=None)
110
110
  async def delete_role(
111
111
  request: Request,
112
112
  role_id: int,
@@ -56,6 +56,7 @@ async def get_search_suggestions(
56
56
  if registry is None or not q.strip():
57
57
  return {"suggestions": [], "query": q}
58
58
 
59
+ admin_path = request.app.state.admin_config["admin_path"]
59
60
  query_lower = q.strip().lower()
60
61
  suggestions: list[dict[str, Any]] = []
61
62
 
@@ -79,7 +80,7 @@ async def get_search_suggestions(
79
80
  "model": table_name,
80
81
  "label": verbose_name_plural,
81
82
  "sublabel": table_name,
82
- "url": f"/admin/{table_name}",
83
+ "url": f"{admin_path}/{table_name}",
83
84
  }
84
85
  )
85
86
 
@@ -120,7 +121,7 @@ async def get_search_suggestions(
120
121
  "field": field_name,
121
122
  "label": f"{verbose_name_plural} → {field_label}",
122
123
  "sublabel": f"{table_name}.{field_name}",
123
- "url": f"/admin/{table_name}?q={q}",
124
+ "url": f"{admin_path}/{table_name}?q={q}",
124
125
  }
125
126
  )
126
127
 
@@ -9,7 +9,7 @@ import time
9
9
 
10
10
  from fastapi import HTTPException, Request, Response
11
11
  from starlette.middleware.base import BaseHTTPMiddleware
12
- from starlette.responses import JSONResponse, RedirectResponse
12
+ from starlette.responses import RedirectResponse
13
13
 
14
14
  CSRF_COOKIE_NAME = "admin_csrf_token"
15
15
  CSRF_FORM_FIELD = "csrf_token"
@@ -224,9 +224,10 @@ async def auth_redirect_handler(request: Request, exc: HTTPException) -> Respons
224
224
  if exc.status_code == 401:
225
225
  accept = request.headers.get("accept", "")
226
226
  if "text/html" in accept:
227
- login_url = "/admin/login"
227
+ admin_path = request.app.state.admin_config["admin_path"]
228
+ login_url = f"{admin_path}/login"
228
229
  current_path = request.url.path
229
- if current_path != "/admin/login":
230
+ if current_path != f"{admin_path}/login":
230
231
  if request.url.query:
231
232
  login_url += f"?next={current_path}%3F{request.url.query}"
232
233
  else:
@@ -45,7 +45,8 @@ async def login_get(
45
45
  ) -> HTMLResponse:
46
46
  """GET /admin/login — show login page, redirect if already logged in."""
47
47
  if session_payload is not None:
48
- target = next if _is_safe_url(next) else "/admin/"
48
+ admin_path = request.app.state.admin_config["admin_path"]
49
+ target = next if _is_safe_url(next) else f"{admin_path}/"
49
50
  return RedirectResponse(url=target, status_code=status.HTTP_302_FOUND)
50
51
 
51
52
  jinja_env = request.app.state.admin_jinja_env
@@ -90,7 +91,8 @@ async def login_post(
90
91
  if next and _is_safe_url(next):
91
92
  redirect_url = next
92
93
  else:
93
- redirect_url = "/admin/"
94
+ admin_path = request.app.state.admin_config["admin_path"]
95
+ redirect_url = f"{admin_path}/"
94
96
 
95
97
  samesite = getattr(
96
98
  request.app.state.admin_state, "session_samesite", "strict"
@@ -149,7 +151,8 @@ async def logout_post(
149
151
  request.app.state.admin_state, "session_samesite", "strict"
150
152
  )
151
153
  response = RedirectResponse(
152
- url="/admin/login", status_code=status.HTTP_302_FOUND
154
+ url=f"{request.app.state.admin_config['admin_path']}/login",
155
+ status_code=status.HTTP_302_FOUND
153
156
  )
154
157
  response.delete_cookie(
155
158
  key=session_backend.cookie_name,
@@ -0,0 +1,79 @@
1
+ """CLI commands for FastAPI Admin Kit."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import sys
7
+
8
+ from fastapi_admin_kit.cli.scaffold import scaffold_project
9
+ from fastapi_admin_kit.cli.user import (
10
+ handle_user_command,
11
+ register_user_commands,
12
+ )
13
+
14
+
15
+ def _init_project(args: argparse.Namespace) -> None:
16
+ """Create a new FastAPI project with uv."""
17
+ scaffold_project(
18
+ project_name=args.name,
19
+ layout=args.layout,
20
+ directory=args.directory,
21
+ skip_venv=args.no_venv,
22
+ skip_git=args.no_git,
23
+ )
24
+
25
+
26
+ def main() -> None:
27
+ """Main CLI entry point."""
28
+ parser = argparse.ArgumentParser(
29
+ description="FastAPI Admin Kit CLI — manage admin users and scaffold projects.",
30
+ )
31
+ subparsers = parser.add_subparsers(
32
+ dest="command", help="Available commands"
33
+ )
34
+
35
+ # Register command groups
36
+ register_user_commands(subparsers)
37
+
38
+ # init — scaffold a new FastAPI project
39
+ init_parser = subparsers.add_parser(
40
+ "init", help="Create a new FastAPI project with uv"
41
+ )
42
+ init_parser.add_argument(
43
+ "name", nargs="?", default=None, help="Project name"
44
+ )
45
+ init_parser.add_argument(
46
+ "-l",
47
+ "--layout",
48
+ choices=["flat", "app", "src"],
49
+ default=None,
50
+ help="Project layout (flat, app, src). Interactive if omitted.",
51
+ )
52
+ init_parser.add_argument(
53
+ "-d",
54
+ "--directory",
55
+ default=None,
56
+ help="Target directory (defaults to project name)",
57
+ )
58
+ init_parser.add_argument(
59
+ "--no-venv", action="store_true", help="Skip uv venv creation"
60
+ )
61
+ init_parser.add_argument(
62
+ "--no-git", action="store_true", help="Skip git init"
63
+ )
64
+
65
+ args = parser.parse_args()
66
+
67
+ if args.command is None:
68
+ parser.print_help()
69
+ sys.exit(1)
70
+
71
+ # Dispatch
72
+ if args.command in ("createsuperuser", "users", "changepassword"):
73
+ handle_user_command(args)
74
+ elif args.command == "init":
75
+ _init_project(args)
76
+
77
+
78
+ if __name__ == "__main__":
79
+ main()
@@ -0,0 +1,5 @@
1
+ """Allow running CLI as `python -m fastapi_admin_kit.cli`."""
2
+
3
+ from fastapi_admin_kit.cli import main
4
+
5
+ main()
@@ -0,0 +1,287 @@
1
+ """Interactive project scaffolding for FastAPI projects with uv."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import subprocess
6
+ import sys
7
+ from pathlib import Path
8
+
9
+ LAYOUTS = {
10
+ "flat": {
11
+ "name": "Flat (main.py in root)",
12
+ "description": "Simple layout — main.py at project root",
13
+ "files": {
14
+ "main.py": '''\
15
+ from contextlib import asynccontextmanager
16
+
17
+ from fastapi import FastAPI
18
+
19
+
20
+ @asynccontextmanager
21
+ async def lifespan(app: FastAPI):
22
+ print("Starting up...")
23
+ yield
24
+ print("Shutting down...")
25
+
26
+
27
+ app = FastAPI(title="{project_name}", lifespan=lifespan)
28
+
29
+
30
+ @app.get("/")
31
+ async def root():
32
+ return {{"message": "Hello from {project_name}!"}}
33
+
34
+
35
+ @app.get("/health")
36
+ async def health():
37
+ return {{"status": "ok"}}
38
+ ''',
39
+ },
40
+ },
41
+ "app": {
42
+ "name": "App directory (app/main.py)",
43
+ "description": "Recommended — app/ package with __init__.py",
44
+ "files": {
45
+ "app/__init__.py": "",
46
+ "app/main.py": '''\
47
+ from contextlib import asynccontextmanager
48
+
49
+ from fastapi import FastAPI
50
+
51
+
52
+ @asynccontextmanager
53
+ async def lifespan(app: FastAPI):
54
+ print("Starting up...")
55
+ yield
56
+ print("Shutting down...")
57
+
58
+
59
+ app = FastAPI(title="{project_name}", lifespan=lifespan)
60
+
61
+
62
+ @app.get("/")
63
+ async def root():
64
+ return {{"message": "Hello from {project_name}!"}}
65
+
66
+
67
+ @app.get("/health")
68
+ async def health():
69
+ return {{"status": "ok"}}
70
+ ''',
71
+ },
72
+ },
73
+ "src": {
74
+ "name": "Src layout (src/app/main.py)",
75
+ "description": "Src layout — installable package with src/ root",
76
+ "files": {
77
+ "src/__init__.py": "",
78
+ "src/app/__init__.py": "",
79
+ "src/app/main.py": '''\
80
+ from contextlib import asynccontextmanager
81
+
82
+ from fastapi import FastAPI
83
+
84
+
85
+ @asynccontextmanager
86
+ async def lifespan(app: FastAPI):
87
+ print("Starting up...")
88
+ yield
89
+ print("Shutting down...")
90
+
91
+
92
+ app = FastAPI(title="{project_name}", lifespan=lifespan)
93
+
94
+
95
+ @app.get("/")
96
+ async def root():
97
+ return {{"message": "Hello from {project_name}!"}}
98
+
99
+
100
+ @app.get("/health")
101
+ async def health():
102
+ return {{"status": "ok"}}
103
+ ''',
104
+ },
105
+ },
106
+ }
107
+
108
+
109
+ def _pyproject_content(project_name: str, layout: str, description: str = "") -> str:
110
+ """Generate pyproject.toml content."""
111
+ entrypoints = {
112
+ "flat": "main:app",
113
+ "app": "app.main:app",
114
+ "src": "app.main:app",
115
+ }
116
+ packages_val = {
117
+ "flat": "main.py",
118
+ "app": "app",
119
+ "src": "src/app",
120
+ }
121
+
122
+ return f'''\
123
+ [project]
124
+ name = "{project_name}"
125
+ version = "0.1.0"
126
+ description = "{description or project_name}"
127
+ readme = "README.md"
128
+ requires-python = ">=3.11"
129
+ dependencies = [
130
+ "fastapi[standard]>=0.115.0",
131
+ "uvicorn[standard]>=0.30.0",
132
+ ]
133
+
134
+ [tool.hatch.build.targets.wheel]
135
+ packages = ["{packages_val[layout]}"]
136
+
137
+ [tool.fastapi]
138
+ entrypoint = "{entrypoints[layout]}"
139
+
140
+ [build-system]
141
+ requires = ["hatchling"]
142
+ build-backend = "hatchling.build"
143
+
144
+ [tool.ruff]
145
+ line-length = 100
146
+ target-version = "py311"
147
+ '''
148
+
149
+
150
+ def _gitignore_content() -> str:
151
+ return '''\
152
+ __pycache__/
153
+ *.py[cod]
154
+ *.egg-info/
155
+ dist/
156
+ build/
157
+ .venv/
158
+ .env
159
+ *.db
160
+ *.sqlite3
161
+ '''
162
+
163
+
164
+ def _python_version_content() -> str:
165
+ return "3.11\n"
166
+
167
+
168
+ def _input(prompt: str, default: str = "") -> str:
169
+ """Read user input with optional default."""
170
+ suffix = f" [{default}]" if default else ""
171
+ value = input(f"{prompt}{suffix}: ").strip()
172
+ return value or default
173
+
174
+
175
+ def _select(options: list[str], prompt: str) -> int:
176
+ """Display numbered options and return selected index."""
177
+ print(f"\n{prompt}")
178
+ for i, opt in enumerate(options, 1):
179
+ print(f" {i}) {opt}")
180
+ while True:
181
+ choice = input("\nEnter number: ").strip()
182
+ if choice.isdigit() and 1 <= int(choice) <= len(options):
183
+ return int(choice) - 1
184
+ print(f"Invalid choice. Enter 1-{len(options)}.")
185
+
186
+
187
+ def _run(cmd: list[str], cwd: Path) -> bool:
188
+ """Run a subprocess, return True on success."""
189
+ result = subprocess.run(cmd, cwd=cwd, capture_output=True, text=True)
190
+ if result.returncode != 0:
191
+ print(f"Error running {' '.join(cmd)}:")
192
+ print(result.stderr or result.stdout)
193
+ return False
194
+ return True
195
+
196
+
197
+ def scaffold_project(
198
+ project_name: str | None = None,
199
+ layout: str | None = None,
200
+ directory: str | None = None,
201
+ skip_venv: bool = False,
202
+ skip_git: bool = False,
203
+ ) -> Path:
204
+ """
205
+ Create a new FastAPI project.
206
+
207
+ Interactive when args are missing; non-interactive when all provided.
208
+ Returns the project directory path.
209
+ """
210
+ # --- Collect inputs interactively ---
211
+ if not project_name:
212
+ project_name = _input("Project name", "my-fastapi-app")
213
+
214
+ if not layout:
215
+ options = [f"{LAYOUTS[k]['name']} — {LAYOUTS[k]['description']}" for k in LAYOUTS]
216
+ idx = _select(options, "Select project structure:")
217
+ layout = list(LAYOUTS.keys())[idx]
218
+
219
+ project_dir = Path(directory or project_name).resolve()
220
+
221
+ if project_dir.exists() and any(project_dir.iterdir()):
222
+ confirm = _input(f"'{project_dir}' already exists. Overwrite?", "n")
223
+ if confirm.lower() not in ("y", "yes"):
224
+ print("Aborted.")
225
+ sys.exit(1)
226
+
227
+ project_dir.mkdir(parents=True, exist_ok=True)
228
+
229
+ # --- Write files ---
230
+ print(f"\nCreating project '{project_name}' in {project_dir} ...")
231
+
232
+ # pyproject.toml
233
+ (project_dir / "pyproject.toml").write_text(_pyproject_content(project_name, layout))
234
+
235
+ # .gitignore
236
+ (project_dir / ".gitignore").write_text(_gitignore_content())
237
+
238
+ # .python-version
239
+ (project_dir / ".python-version").write_text(_python_version_content())
240
+
241
+ # README.md
242
+ (project_dir / "README.md").write_text(f"# {project_name}\n\nA FastAPI project.\n")
243
+
244
+ # Layout files
245
+ layout_data = LAYOUTS[layout]
246
+ for rel_path, content in layout_data["files"].items():
247
+ file_path = project_dir / rel_path
248
+ file_path.parent.mkdir(parents=True, exist_ok=True)
249
+ file_path.write_text(content.format(project_name=project_name))
250
+
251
+ print("Project files created.")
252
+
253
+ # --- uv init ---
254
+ if not skip_venv:
255
+ print("\nSetting up virtual environment with uv...")
256
+ if not _run(["uv", "venv"], project_dir):
257
+ print("Warning: uv venv creation failed. Create manually: uv venv")
258
+ else:
259
+ print(" Virtual environment created.")
260
+
261
+ print("Installing dependencies...")
262
+ if not _run(["uv", "sync"], project_dir):
263
+ # uv sync may fail if uv.lock doesn't exist yet, try uv pip install
264
+ print(" Trying uv pip install...")
265
+ _run(["uv", "pip", "install", "-e", "."], project_dir)
266
+ else:
267
+ print(" Dependencies installed.")
268
+
269
+ # --- git init ---
270
+ if not skip_git:
271
+ print("\nInitializing git repository...")
272
+ _run(["git", "init"], project_dir)
273
+ _run(["git", "add", "."], project_dir)
274
+ _run(["git", "commit", "-m", "Initial commit"], project_dir)
275
+ print(" Git repository initialized.")
276
+
277
+ # --- Summary ---
278
+ entrypoints = {"flat": "main:app", "app": "app.main:app", "src": "app.main:app"}
279
+ print(f"\nDone! Project '{project_name}' is ready.\n")
280
+ print(f" cd {project_dir.name}")
281
+ if not skip_venv:
282
+ print(" source .venv/bin/activate # or: uv run fastapi dev")
283
+ print(" fastapi dev # starts at http://localhost:8000")
284
+ print(f"\n Entrypoint: {entrypoints[layout]}")
285
+ print(f" Layout: {LAYOUTS[layout]['name']}")
286
+
287
+ return project_dir