supython 0.1.9__tar.gz → 0.1.11__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 (260) hide show
  1. {supython-0.1.9 → supython-0.1.11}/.gitignore +9 -1
  2. {supython-0.1.9 → supython-0.1.11}/CHANGELOG.md +68 -2
  3. {supython-0.1.9 → supython-0.1.11}/PKG-INFO +46 -152
  4. {supython-0.1.9 → supython-0.1.11}/README.md +44 -151
  5. {supython-0.1.9 → supython-0.1.11}/pyproject.toml +2 -1
  6. {supython-0.1.9 → supython-0.1.11}/src/supython/app.py +2 -1
  7. {supython-0.1.9 → supython-0.1.11}/src/supython/cli.py +33 -13
  8. supython-0.1.11/src/supython/extensions.py +68 -0
  9. supython-0.1.11/src/supython/scaffold/init_project.py +217 -0
  10. supython-0.1.11/src/supython/scaffold/templates/README.md.tmpl +32 -0
  11. supython-0.1.9/src/supython/scaffold/templates/apps_hooks.py.tmpl → supython-0.1.11/src/supython/scaffold/templates/apps_hooks_welcome.py.tmpl +1 -1
  12. supython-0.1.9/src/supython/scaffold/templates/apps_jobs.py.tmpl → supython-0.1.11/src/supython/scaffold/templates/apps_jobs_example.py.tmpl +1 -1
  13. supython-0.1.11/src/supython/scaffold/templates/package_hooks_init.py.tmpl +8 -0
  14. supython-0.1.11/src/supython/scaffold/templates/package_jobs_init.py.tmpl +8 -0
  15. supython-0.1.11/src/supython/scaffold/templates/pyproject.toml.tmpl +15 -0
  16. {supython-0.1.9 → supython-0.1.11}/src/supython/scaffold/templates/settings.py.tmpl +5 -1
  17. supython-0.1.9/src/supython/migrations/0003_demo_todos.sql → supython-0.1.11/src/supython/scaffold/templates/static/0001_create_todos.sql +10 -3
  18. supython-0.1.11/src/supython/scaffold/templates/static/functions_hello.py +13 -0
  19. {supython-0.1.9 → supython-0.1.11}/src/supython/settings.py +31 -0
  20. supython-0.1.9/src/supython/extensions.py +0 -36
  21. supython-0.1.9/src/supython/scaffold/init_project.py +0 -144
  22. supython-0.1.9/src/supython/scaffold/templates/README.md.tmpl +0 -22
  23. supython-0.1.9/src/supython/scaffold/templates/migrations/.gitkeep +0 -0
  24. {supython-0.1.9 → supython-0.1.11}/LICENSE +0 -0
  25. {supython-0.1.9 → supython-0.1.11}/SECURITY.md +0 -0
  26. {supython-0.1.9 → supython-0.1.11}/src/supython/__init__.py +0 -0
  27. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/__init__.py +0 -0
  28. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/__init__.py +0 -0
  29. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/auth.py +0 -0
  30. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/auth_templates.py +0 -0
  31. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/auth_users.py +0 -0
  32. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/db.py +0 -0
  33. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/functions.py +0 -0
  34. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/jobs.py +0 -0
  35. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/ops.py +0 -0
  36. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/realtime.py +0 -0
  37. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/service_auth.py +0 -0
  38. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/service_auth_templates.py +0 -0
  39. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/service_auth_users.py +0 -0
  40. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/service_db.py +0 -0
  41. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/service_functions.py +0 -0
  42. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/service_jobs.py +0 -0
  43. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/service_ops.py +0 -0
  44. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/service_realtime.py +0 -0
  45. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/service_storage.py +0 -0
  46. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/storage.py +0 -0
  47. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/api/system.py +0 -0
  48. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/audit.py +0 -0
  49. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/deps.py +0 -0
  50. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/errors.py +0 -0
  51. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/schemas.py +0 -0
  52. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/session.py +0 -0
  53. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/spa.py +0 -0
  54. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Alert-dluGVkos.js +0 -0
  55. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Alert-dluGVkos.js.map +0 -0
  56. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Audit-Njung3HI.js +0 -0
  57. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Audit-Njung3HI.js.map +0 -0
  58. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Backups-DzPlFgrm.js +0 -0
  59. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Backups-DzPlFgrm.js.map +0 -0
  60. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Buckets-ByacGkU1.js +0 -0
  61. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Buckets-ByacGkU1.js.map +0 -0
  62. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Channels-BoIuTtam.js +0 -0
  63. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Channels-BoIuTtam.js.map +0 -0
  64. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/ChevronRight-CtQH1EQ1.js +0 -0
  65. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/ChevronRight-CtQH1EQ1.js.map +0 -0
  66. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/CodeViewer-Bqy7-wvH.js +0 -0
  67. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/CodeViewer-Bqy7-wvH.js.map +0 -0
  68. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Crons-B67vc39F.js +0 -0
  69. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Crons-B67vc39F.js.map +0 -0
  70. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/DashboardView-CUTFVL6k.js +0 -0
  71. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/DashboardView-CUTFVL6k.js.map +0 -0
  72. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/DataTable-COAAWEft.js +0 -0
  73. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/DataTable-COAAWEft.js.map +0 -0
  74. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/DescriptionsItem-P8JUDaBs.js +0 -0
  75. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/DescriptionsItem-P8JUDaBs.js.map +0 -0
  76. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/DrawerContent-TpYTFgF1.js +0 -0
  77. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/DrawerContent-TpYTFgF1.js.map +0 -0
  78. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Empty-cr2r7e2u.js +0 -0
  79. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Empty-cr2r7e2u.js.map +0 -0
  80. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/EmptyState-DeDck-OL.js +0 -0
  81. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/EmptyState-DeDck-OL.js.map +0 -0
  82. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Grid-hFkp9F4P.js +0 -0
  83. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Grid-hFkp9F4P.js.map +0 -0
  84. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Input-DppYTq9C.js +0 -0
  85. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Input-DppYTq9C.js.map +0 -0
  86. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Invoke-DW3Nveeh.js +0 -0
  87. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Invoke-DW3Nveeh.js.map +0 -0
  88. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/JsonField-DibyJgun.js +0 -0
  89. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/JsonField-DibyJgun.js.map +0 -0
  90. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/LoginView-BjLyE3Ds.css +0 -0
  91. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/LoginView-CoOjECT_.js +0 -0
  92. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/LoginView-CoOjECT_.js.map +0 -0
  93. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Logs-D9WYrnIT.js +0 -0
  94. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Logs-D9WYrnIT.js.map +0 -0
  95. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Logs-DS1XPa0h.css +0 -0
  96. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Migrations-DOSC2ddQ.js +0 -0
  97. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Migrations-DOSC2ddQ.js.map +0 -0
  98. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/ObjectBrowser-_5w8vOX8.js +0 -0
  99. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/ObjectBrowser-_5w8vOX8.js.map +0 -0
  100. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Queue-CywZs6vI.js +0 -0
  101. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Queue-CywZs6vI.js.map +0 -0
  102. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/RefreshTokens-Ccjr53jg.js +0 -0
  103. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/RefreshTokens-Ccjr53jg.js.map +0 -0
  104. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/RlsEditor-BSlH9vSc.js +0 -0
  105. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/RlsEditor-BSlH9vSc.js.map +0 -0
  106. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Routes-BiLXE49D.js +0 -0
  107. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Routes-BiLXE49D.js.map +0 -0
  108. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Routes-C-ianIGD.css +0 -0
  109. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/SchemaBrowser-DKy2_KQi.css +0 -0
  110. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/SchemaBrowser-XFvFbtDB.js +0 -0
  111. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/SchemaBrowser-XFvFbtDB.js.map +0 -0
  112. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Select-DIzZyRZb.js +0 -0
  113. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Select-DIzZyRZb.js.map +0 -0
  114. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Space-n5-XcguU.js +0 -0
  115. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Space-n5-XcguU.js.map +0 -0
  116. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/SqlEditor-b8pTsILY.js +0 -0
  117. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/SqlEditor-b8pTsILY.js.map +0 -0
  118. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/SqlWorkspace-BUS7IntH.js +0 -0
  119. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/SqlWorkspace-BUS7IntH.js.map +0 -0
  120. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/TableData-CQIagLKn.js +0 -0
  121. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/TableData-CQIagLKn.js.map +0 -0
  122. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Tag-D1fOKpTH.js +0 -0
  123. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Tag-D1fOKpTH.js.map +0 -0
  124. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Templates-BS-ugkdq.js +0 -0
  125. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Templates-BS-ugkdq.js.map +0 -0
  126. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Thing-CEAniuMg.js +0 -0
  127. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Thing-CEAniuMg.js.map +0 -0
  128. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Users-wzwajhlh.js +0 -0
  129. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/Users-wzwajhlh.js.map +0 -0
  130. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/_plugin-vue_export-helper-DGA9ry_j.js +0 -0
  131. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/dist-VXIJLCYq.js +0 -0
  132. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/dist-VXIJLCYq.js.map +0 -0
  133. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/format-length-CGCY1rMh.js +0 -0
  134. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/format-length-CGCY1rMh.js.map +0 -0
  135. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/get-Ca6unauB.js +0 -0
  136. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/get-Ca6unauB.js.map +0 -0
  137. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/index-CeE6v959.js +0 -0
  138. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/index-CeE6v959.js.map +0 -0
  139. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/pinia-COXwfrOX.js +0 -0
  140. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/pinia-COXwfrOX.js.map +0 -0
  141. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/resources-Bt6thQCD.js +0 -0
  142. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/resources-Bt6thQCD.js.map +0 -0
  143. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/use-locale-mtgM0a3a.js +0 -0
  144. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/use-locale-mtgM0a3a.js.map +0 -0
  145. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/use-merged-state-BvhkaHNX.js +0 -0
  146. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/use-merged-state-BvhkaHNX.js.map +0 -0
  147. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/useConfirm-tMjvBFXR.js +0 -0
  148. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/useConfirm-tMjvBFXR.js.map +0 -0
  149. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/useResource-C_rJCY8C.js +0 -0
  150. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/useResource-C_rJCY8C.js.map +0 -0
  151. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/useTable-CnZc5zhi.js +0 -0
  152. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/useTable-CnZc5zhi.js.map +0 -0
  153. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/useTable-Dg0XlRlq.css +0 -0
  154. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/useToast-DsZKx0IX.js +0 -0
  155. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/useToast-DsZKx0IX.js.map +0 -0
  156. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/utils-sbXoq7Ir.js +0 -0
  157. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/assets/utils-sbXoq7Ir.js.map +0 -0
  158. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/favicon.svg +0 -0
  159. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/icons.svg +0 -0
  160. {supython-0.1.9 → supython-0.1.11}/src/supython/admin/static/index.html +0 -0
  161. {supython-0.1.9 → supython-0.1.11}/src/supython/auth/__init__.py +0 -0
  162. {supython-0.1.9 → supython-0.1.11}/src/supython/auth/_email_job.py +0 -0
  163. {supython-0.1.9 → supython-0.1.11}/src/supython/auth/claims.py +0 -0
  164. {supython-0.1.9 → supython-0.1.11}/src/supython/auth/deps.py +0 -0
  165. {supython-0.1.9 → supython-0.1.11}/src/supython/auth/providers/__init__.py +0 -0
  166. {supython-0.1.9 → supython-0.1.11}/src/supython/auth/providers/github.py +0 -0
  167. {supython-0.1.9 → supython-0.1.11}/src/supython/auth/providers/google.py +0 -0
  168. {supython-0.1.9 → supython-0.1.11}/src/supython/auth/providers/oauth.py +0 -0
  169. {supython-0.1.9 → supython-0.1.11}/src/supython/auth/providers/registry.py +0 -0
  170. {supython-0.1.9 → supython-0.1.11}/src/supython/auth/ratelimit.py +0 -0
  171. {supython-0.1.9 → supython-0.1.11}/src/supython/auth/router.py +0 -0
  172. {supython-0.1.9 → supython-0.1.11}/src/supython/auth/schemas.py +0 -0
  173. {supython-0.1.9 → supython-0.1.11}/src/supython/auth/service.py +0 -0
  174. {supython-0.1.9 → supython-0.1.11}/src/supython/backups/__init__.py +0 -0
  175. {supython-0.1.9 → supython-0.1.11}/src/supython/backups/_backup_job.py +0 -0
  176. {supython-0.1.9 → supython-0.1.11}/src/supython/backups/schemas.py +0 -0
  177. {supython-0.1.9 → supython-0.1.11}/src/supython/backups/service.py +0 -0
  178. {supython-0.1.9 → supython-0.1.11}/src/supython/body_size.py +0 -0
  179. {supython-0.1.9 → supython-0.1.11}/src/supython/client/__init__.py +0 -0
  180. {supython-0.1.9 → supython-0.1.11}/src/supython/client/_auth.py +0 -0
  181. {supython-0.1.9 → supython-0.1.11}/src/supython/client/_client.py +0 -0
  182. {supython-0.1.9 → supython-0.1.11}/src/supython/client/_config.py +0 -0
  183. {supython-0.1.9 → supython-0.1.11}/src/supython/client/_functions.py +0 -0
  184. {supython-0.1.9 → supython-0.1.11}/src/supython/client/_storage.py +0 -0
  185. {supython-0.1.9 → supython-0.1.11}/src/supython/client/py.typed +0 -0
  186. {supython-0.1.9 → supython-0.1.11}/src/supython/db.py +0 -0
  187. {supython-0.1.9 → supython-0.1.11}/src/supython/db_admin.py +0 -0
  188. {supython-0.1.9 → supython-0.1.11}/src/supython/functions/__init__.py +0 -0
  189. {supython-0.1.9 → supython-0.1.11}/src/supython/functions/context.py +0 -0
  190. {supython-0.1.9 → supython-0.1.11}/src/supython/functions/loader.py +0 -0
  191. {supython-0.1.9 → supython-0.1.11}/src/supython/functions/router.py +0 -0
  192. {supython-0.1.9 → supython-0.1.11}/src/supython/functions/schemas.py +0 -0
  193. {supython-0.1.9 → supython-0.1.11}/src/supython/gen/__init__.py +0 -0
  194. {supython-0.1.9 → supython-0.1.11}/src/supython/gen/_introspect.py +0 -0
  195. {supython-0.1.9 → supython-0.1.11}/src/supython/gen/types_py.py +0 -0
  196. {supython-0.1.9 → supython-0.1.11}/src/supython/gen/types_ts.py +0 -0
  197. {supython-0.1.9 → supython-0.1.11}/src/supython/health.py +0 -0
  198. {supython-0.1.9 → supython-0.1.11}/src/supython/hooks.py +0 -0
  199. {supython-0.1.9 → supython-0.1.11}/src/supython/jobs/__init__.py +0 -0
  200. {supython-0.1.9 → supython-0.1.11}/src/supython/jobs/backends.py +0 -0
  201. {supython-0.1.9 → supython-0.1.11}/src/supython/jobs/context.py +0 -0
  202. {supython-0.1.9 → supython-0.1.11}/src/supython/jobs/cron.py +0 -0
  203. {supython-0.1.9 → supython-0.1.11}/src/supython/jobs/cron_inproc.py +0 -0
  204. {supython-0.1.9 → supython-0.1.11}/src/supython/jobs/decorators.py +0 -0
  205. {supython-0.1.9 → supython-0.1.11}/src/supython/jobs/registry.py +0 -0
  206. {supython-0.1.9 → supython-0.1.11}/src/supython/jobs/router.py +0 -0
  207. {supython-0.1.9 → supython-0.1.11}/src/supython/jobs/schemas.py +0 -0
  208. {supython-0.1.9 → supython-0.1.11}/src/supython/jobs/service.py +0 -0
  209. {supython-0.1.9 → supython-0.1.11}/src/supython/jobs/worker.py +0 -0
  210. {supython-0.1.9 → supython-0.1.11}/src/supython/jwks.py +0 -0
  211. {supython-0.1.9 → supython-0.1.11}/src/supython/keyset.py +0 -0
  212. {supython-0.1.9 → supython-0.1.11}/src/supython/logging_config.py +0 -0
  213. {supython-0.1.9 → supython-0.1.11}/src/supython/mail.py +0 -0
  214. {supython-0.1.9 → supython-0.1.11}/src/supython/mailer.py +0 -0
  215. {supython-0.1.9 → supython-0.1.11}/src/supython/migrate.py +0 -0
  216. {supython-0.1.9 → supython-0.1.11}/src/supython/migrations/0001_extensions_and_roles.sql +0 -0
  217. {supython-0.1.9 → supython-0.1.11}/src/supython/migrations/0002_auth_schema.sql +0 -0
  218. {supython-0.1.9 → supython-0.1.11}/src/supython/migrations/0004_auth_v0_2.sql +0 -0
  219. {supython-0.1.9 → supython-0.1.11}/src/supython/migrations/0005_storage_schema.sql +0 -0
  220. {supython-0.1.9 → supython-0.1.11}/src/supython/migrations/0006_realtime_schema.sql +0 -0
  221. {supython-0.1.9 → supython-0.1.11}/src/supython/migrations/0007_jobs_schema.sql +0 -0
  222. {supython-0.1.9 → supython-0.1.11}/src/supython/migrations/0008_jobs_last_error.sql +0 -0
  223. {supython-0.1.9 → supython-0.1.11}/src/supython/migrations/0009_auth_rate_limits.sql +0 -0
  224. {supython-0.1.9 → supython-0.1.11}/src/supython/migrations/0010_worker_heartbeat.sql +0 -0
  225. {supython-0.1.9 → supython-0.1.11}/src/supython/migrations/0011_admin_schema.sql +0 -0
  226. {supython-0.1.9 → supython-0.1.11}/src/supython/migrations/0012_auth_banned_until.sql +0 -0
  227. {supython-0.1.9 → supython-0.1.11}/src/supython/migrations/0013_email_templates.sql +0 -0
  228. {supython-0.1.9 → supython-0.1.11}/src/supython/migrations/0014_realtime_payload_warning.sql +0 -0
  229. {supython-0.1.9 → supython-0.1.11}/src/supython/migrations/0015_backups_schema.sql +0 -0
  230. {supython-0.1.9 → supython-0.1.11}/src/supython/passwords.py +0 -0
  231. {supython-0.1.9 → supython-0.1.11}/src/supython/realtime/__init__.py +0 -0
  232. {supython-0.1.9 → supython-0.1.11}/src/supython/realtime/broker.py +0 -0
  233. {supython-0.1.9 → supython-0.1.11}/src/supython/realtime/protocol.py +0 -0
  234. {supython-0.1.9 → supython-0.1.11}/src/supython/realtime/router.py +0 -0
  235. {supython-0.1.9 → supython-0.1.11}/src/supython/realtime/schemas.py +0 -0
  236. {supython-0.1.9 → supython-0.1.11}/src/supython/realtime/service.py +0 -0
  237. {supython-0.1.9 → supython-0.1.11}/src/supython/realtime/topics.py +0 -0
  238. {supython-0.1.9 → supython-0.1.11}/src/supython/realtime/websocket.py +0 -0
  239. {supython-0.1.9 → supython-0.1.11}/src/supython/scaffold/__init__.py +0 -0
  240. {supython-0.1.9 → supython-0.1.11}/src/supython/scaffold/templates/Caddyfile.tmpl +0 -0
  241. {supython-0.1.9 → supython-0.1.11}/src/supython/scaffold/templates/asgi.py.tmpl +0 -0
  242. {supython-0.1.9 → supython-0.1.11}/src/supython/scaffold/templates/docker-compose.prod.yml.tmpl +0 -0
  243. {supython-0.1.9 → supython-0.1.11}/src/supython/scaffold/templates/docker-compose.yml.tmpl +0 -0
  244. {supython-0.1.9 → supython-0.1.11}/src/supython/scaffold/templates/docker_postgres_Dockerfile.tmpl +0 -0
  245. {supython-0.1.9 → supython-0.1.11}/src/supython/scaffold/templates/docker_postgres_postgresql.conf.tmpl +0 -0
  246. {supython-0.1.9 → supython-0.1.11}/src/supython/scaffold/templates/env.example.tmpl +0 -0
  247. {supython-0.1.9 → supython-0.1.11}/src/supython/scaffold/templates/functions_README.md.tmpl +0 -0
  248. {supython-0.1.9 → supython-0.1.11}/src/supython/scaffold/templates/gitignore.tmpl +0 -0
  249. {supython-0.1.9 → supython-0.1.11}/src/supython/scaffold/templates/manage.py.tmpl +0 -0
  250. {supython-0.1.9 → supython-0.1.11}/src/supython/scaffold/templates/package_init.py.tmpl +0 -0
  251. {supython-0.1.9 → supython-0.1.11}/src/supython/secretset.py +0 -0
  252. {supython-0.1.9 → supython-0.1.11}/src/supython/security_headers.py +0 -0
  253. {supython-0.1.9 → supython-0.1.11}/src/supython/settings_module.py +0 -0
  254. {supython-0.1.9 → supython-0.1.11}/src/supython/storage/__init__.py +0 -0
  255. {supython-0.1.9 → supython-0.1.11}/src/supython/storage/backends.py +0 -0
  256. {supython-0.1.9 → supython-0.1.11}/src/supython/storage/router.py +0 -0
  257. {supython-0.1.9 → supython-0.1.11}/src/supython/storage/schemas.py +0 -0
  258. {supython-0.1.9 → supython-0.1.11}/src/supython/storage/service.py +0 -0
  259. {supython-0.1.9 → supython-0.1.11}/src/supython/storage/signing.py +0 -0
  260. {supython-0.1.9 → supython-0.1.11}/src/supython/tokens.py +0 -0
@@ -29,7 +29,8 @@ dev-app/backups/
29
29
  dev-app/__pycache__/
30
30
  dev-app/functions/__pycache__/
31
31
  dev-app/.tmp/
32
-
32
+ dev-app/
33
+ examples/
33
34
  .references/
34
35
  .references/*.md
35
36
  .claude/
@@ -43,3 +44,10 @@ ts-sdk/*.log
43
44
  .tmp/
44
45
 
45
46
  admin-ui/node_modules/
47
+
48
+ /.supython/secrets/
49
+ /.supython/secrets.json
50
+ /.supython/jwt_private.pem
51
+ /.supython/keys/
52
+ /.supython/keyset.json
53
+ /.supython/jwks.json
@@ -2,8 +2,7 @@
2
2
 
3
3
  All notable changes to supython are recorded here. The format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the
5
- project uses **ZeroVer** (`0.x.y`) see `docs/PROJECT.md` §14.0 for
6
- what counts as a breaking change. There is no scheduled `1.0.0`; treat
5
+ project uses **ZeroVer** (`0.x.y`). There is no scheduled `1.0.0`; treat
7
6
  every `MINOR` as a potential breaking release.
8
7
 
9
8
  Categories used per release:
@@ -31,6 +30,71 @@ Each entry links the relevant `PROJECT.md` section and decision-log row
31
30
 
32
31
  ---
33
32
 
33
+ ## [0.1.11] — 2026-06-13
34
+
35
+ Project-initialization ergonomics. `supython init` now produces a project that
36
+ boots with no manual setup.
37
+
38
+ ### Breaking
39
+
40
+ - `supython init` arguments changed. The first argument is now the **importable
41
+ package name** (still required); the optional second argument is the **target
42
+ directory** (Django-style — `.` for the current directory), defaulting to
43
+ `./<name>`. The `--here` flag is **removed**: `supython init myapp --here`
44
+ becomes `supython init myapp .`.
45
+ - The scaffolded `jobs.py` and `hooks.py` single-file seeds are replaced by
46
+ auto-discovered **packages** `<name>/jobs/` and `<name>/hooks/`. Every module
47
+ inside each package is imported at boot, so jobs and hooks can be split across
48
+ files. `EXTENSIONS` in `settings.py` now points at the packages (`<name>.jobs`,
49
+ `<name>.hooks`) rather than the old modules.
50
+
51
+ ### Added
52
+
53
+ - `supython init` generates a ready-to-run, gitignored `.env` (from the example
54
+ template) so the stack boots without a manual `cp .env.example .env` step.
55
+ - `supython init` generates a `pyproject.toml` that declares the project and
56
+ pins the installed supython version; install the scaffold with `pip install -e .`.
57
+ - The scaffold seeds an example edge function (`functions/hello.py`) and an
58
+ example application migration (`migrations/0001_create_todos.sql`).
59
+
60
+ ### Changed
61
+
62
+ - Re-running `supython init` is now a safe top-up: existing files are skipped,
63
+ not overwritten, unless `--force` is passed.
64
+ - The generated JWT keypair and signing secrets under `.supython/` are **never**
65
+ overwritten — not even with `--force` — to avoid silently rotating keys and
66
+ invalidating live tokens, sessions, and signed URLs. Rotation has dedicated
67
+ homes: `supython keygen` and `supython secret rotate`.
68
+ - The scaffolded `todos` table moved out of supython's framework migrations into
69
+ the project's own `migrations/`. `supython migrate` applies only supython's
70
+ framework schemas (auth, storage, realtime, jobs); apply your application
71
+ migrations with a tool of your choice (dbmate recommended).
72
+
73
+ ---
74
+
75
+ ## [0.1.10] — 2026-06-12
76
+
77
+ ### Added
78
+
79
+ - `python-dotenv` is now a direct dependency (previously only transitive via
80
+ `pydantic-settings`), backing the new boot-time `.env` export.
81
+
82
+ ### Fixed
83
+
84
+ - `.env` is now exported into `os.environ` at the start of every boot path
85
+ (`create_app`, `supython worker run`, CLI subcommands) via the shared
86
+ `settings.export_env_file()` helper, **before** extensions load. Previously
87
+ pydantic-settings loaded `.env` into the typed `Settings` model only, so
88
+ dynamically-named secrets read via `os.environ.get(<name>)` (the `secret_ref`
89
+ convention) resolved to `None` under `supython dev` / `worker run` / CLI —
90
+ working in containers only because docker-compose's `env_file:` injected
91
+ `.env` first. The export uses `override=False`, so real environment variables
92
+ set by an orchestrator always win, and the path is sourced from the same
93
+ `SettingsConfigDict.env_file`. Downstream apps can delete their ad-hoc
94
+ `load_dotenv()` boot shims. (#1)
95
+
96
+ ---
97
+
34
98
  ## [0.1.9] — 2026-05-29
35
99
 
36
100
  ### Fixed
@@ -234,5 +298,7 @@ v0.1–v0.7 plus a v1.1.x admin track; see §19 decision log
234
298
  ---
235
299
 
236
300
 
301
+ [0.1.11]: https://github.com/Tkeby/supython/releases/tag/v0.1.11
302
+ [0.1.10]: https://github.com/Tkeby/supython/releases/tag/v0.1.10
237
303
  [0.1.9]: https://github.com/Tkeby/supython/releases/tag/v0.1.9
238
304
  [0.1.0]: https://github.com/Tkeby/supython/releases/tag/v0.1.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: supython
3
- Version: 0.1.9
3
+ Version: 0.1.11
4
4
  Summary: A lightweight Postgres-first BaaS framework for Python
5
5
  Project-URL: Homepage, https://github.com/Tkeby/supython
6
6
  Project-URL: Repository, https://github.com/Tkeby/supython
@@ -35,6 +35,7 @@ Requires-Dist: itsdangerous>=2.2
35
35
  Requires-Dist: pydantic-settings>=2.6
36
36
  Requires-Dist: pydantic>=2.9
37
37
  Requires-Dist: pyjwt[crypto]>=2.10
38
+ Requires-Dist: python-dotenv>=1.0
38
39
  Requires-Dist: python-multipart>=0.0.20
39
40
  Requires-Dist: typer>=0.15
40
41
  Requires-Dist: uvicorn[standard]>=0.32
@@ -152,20 +153,25 @@ python -m venv .venv && source .venv/bin/activate
152
153
  pip install supython
153
154
 
154
155
  # 2. scaffold a new project
156
+ # `myapp` is the importable package name. An optional second argument
157
+ # sets the target dir (`.` = current dir); it defaults to ./myapp.
155
158
  supython init myapp
156
159
  cd myapp
157
- cp .env.example .env
158
- # Review .env — at minimum confirm AUTHENTICATOR_PASSWORD matches
159
- # the value PostgREST will use (docker-compose.yml injects it via env).
160
+ # install the project (and supython, pinned in the generated pyproject.toml)
161
+ pip install -e .
160
162
  #
161
- # The scaffold creates:
162
- # manage.py Optional CLI entrypoint (sets SUPYTHON_SETTINGS_MODULE)
163
+ # The scaffold generates a ready-to-run, gitignored .env plus a JWT keypair
164
+ # and signing secrets under .supython/ no manual edits needed to boot.
165
+ # It also creates:
166
+ # pyproject.toml — declares this project, pins the supython version
163
167
  # myapp/settings.py — declare EXTENSIONS, EXTRA_ROUTERS, EXTRA_MIDDLEWARE
164
- # myapp/jobs.py example @job seed (register your background jobs here)
165
- # myapp/hooks.py example @on("signup") seed (lifecycle hooks)
168
+ # myapp/jobs/ package of @job / @cron modules (all auto-imported)
169
+ # myapp/hooks/ package of @on(...) lifecycle hooks (all auto-imported)
166
170
  # myapp/asgi.py — optional entrypoint for uvicorn/gunicorn
171
+ # functions/hello.py — example edge function (GET /functions/hello)
172
+ # migrations/0001_create_todos.sql — example app migration (apply with dbmate)
167
173
 
168
- # 3. boot Postgres + PostgREST and run migrations (one command)
174
+ # 3. boot Postgres + PostgREST and apply supython's framework migrations
169
175
  supython up
170
176
 
171
177
  # 4. run the auth/API service (separate terminal)
@@ -190,6 +196,10 @@ You should now have:
190
196
 
191
197
  ## End-to-end smoke test
192
198
 
199
+ This uses the scaffolded `todos` table, so first apply the example app migration
200
+ (`migrations/0001_create_todos.sql`) with [dbmate](https://github.com/amacneil/dbmate)
201
+ or your migration tool of choice — `supython migrate` only handles framework schemas.
202
+
193
203
  ```bash
194
204
  # sign up
195
205
  curl -sS -X POST http://localhost:8000/auth/v1/signup \
@@ -531,128 +541,31 @@ need to edit SQL.
531
541
 
532
542
  ```
533
543
  supython/
534
- ├── manage.py # optional cli entrypoint (sets SUPYTHON_SETTINGS_MODULE)
535
- ├── docker-compose.yml # Postgres + PostgREST (dev stack)
536
- ├── docker-compose.prod.yml # hardened single-host production stack
537
- ├── docker-compose.test.yml # dedicated test Postgres on port 54323
538
- ├── Caddyfile # reverse-proxy TLS for prod
539
- ├── <name>/ # your Python package
540
- │ ├── __init__.py
541
- │ ├── settings.py # project settings (EXTENSIONS, EXTRA_ROUTERS, …)
542
- │ ├── asgi.py # optional ASGI entrypoint (uvicorn <name>.asgi:app)
543
- │ ├── jobs.py # example @job seed
544
- └── hooks.py # example @on("signup") seed
545
- ├── migrations/
546
- │ ├── 0001_extensions_and_roles.sql # anon/authenticated/service_role/authenticator
547
- │ ├── 0002_auth_schema.sql # auth.users, auth.refresh_tokens, auth.uid()
548
- │ ├── 0003_demo_todos.sql # the demo table + RLS policies
549
- │ ├── 0004_auth_v0_2.sql # identities, one_time_tokens, audit_log
550
- │ ├── 0005_storage_schema.sql # storage.buckets + storage.objects
551
- ├── 0006_realtime_schema.sql # realtime schema, trigger, enable() helper
552
- ├── 0007_jobs_schema.sql # jobs queue, cron_schedules, enqueue/claim_next
553
- ├── 0008_jobs_last_error.sql # last_error column on jobs.jobs
554
- ├── 0009_auth_rate_limits.sql # auth fixed-window rate-limit counters
555
- ├── 0010_worker_heartbeat.sql # worker heartbeat for /readyz
556
- ├── 0011_admin_schema.sql # admin.admin_users, sessions, audit
557
- ├── 0012_auth_banned_until.sql # banned_until on auth.users
558
- │ ├── 0013_email_templates.sql # auth.email_templates
559
- │ ├── 0014_realtime_payload_warning.sql # >8KB payload warning counter
560
- │ └── 0015_backups_schema.sql # backups metadata
561
- ├── examples/
562
- │ ├── todos.http # HTTP smoke tests (auth + PostgREST)
563
- │ ├── storage.http # storage upload / signed URL examples
564
- │ ├── functions.http # edge-function call examples
565
- │ └── chat.html # two-browser realtime demo (vanilla JS, zero deps)
566
- ├── docs/
567
- │ ├── PROJECT.md # architecture + roadmap (single source of truth)
568
- │ ├── Installation.md # full install guide (dev, prod, managed Postgres)
569
- │ └── admin-ui/
570
- │ ├── admin-surface-plan.md # admin implementation plan + phase status
571
- │ └── admin-surface.md # admin architecture + contracts
572
- ├── tests/
573
- │ ├── conftest.py # cross-tree fixtures (keys, capturing mailer)
574
- │ ├── _keys.py # JWT-forging helpers
575
- │ ├── fixtures/ # test function modules, etc.
576
- │ ├── unit/ # pure-Python tests (~6s, no Docker)
577
- │ │ ├── test_admin_session.py
578
- │ │ ├── test_admin_service_db.py
579
- │ │ └── ...
580
- │ └── integration/ # full ASGI + Postgres on port 54323
581
- │ ├── conftest.py # pool, app, client, autouse DB cleaners
582
- │ ├── test_auth_signup_login.py
583
- │ ├── test_admin_auth.py
584
- │ ├── test_admin_auth_users.py
585
- │ ├── test_admin_db_rows.py
586
- │ ├── test_admin_jobs.py
587
- │ ├── test_admin_ops_backups.py
588
- │ ├── test_admin_storage.py
589
- │ ├── test_postgrest_rls.py
590
- │ ├── test_realtime_ws.py
591
- │ └── ...
592
- ├── admin-ui/ # Vue 3 + Vite SPA (built → src/supython/admin/static/)
593
- │ └── src/
594
- │ ├── api/ # single fetch seam
595
- │ ├── components/ # shell, data, editors, feedback
596
- │ ├── composables/ # useResource, useTable, useConfirm, useImpersonate, …
597
- │ ├── stores/ # auth, ui
598
- │ ├── views/ # Dashboard, db/, auth/, storage/, functions/, …
599
- │ └── router/
600
- └── src/supython/
601
- ├── __init__.py # single version string
602
- ├── settings.py # pydantic-settings, .env-driven
603
- ├── db.py # asyncpg pool + lifespan + as_role() / as_service_role()
604
- ├── mailer.py # ConsoleBackend / SmtpBackend
605
- ├── tokens.py # RS256/ES256 JWT + JWKS
606
- ├── passwords.py # argon2id
607
- ├── migrate.py # ~50-line SQL migration runner
608
- ├── app.py # FastAPI factory
609
- ├── cli.py # typer: up, dev, keygen, admin, worker, test, …
610
- ├── extensions.py # eager-import dotted module paths at boot
611
- ├── settings_module.py # user settings (EXTENSIONS, EXTRA_ROUTERS, …)
612
- ├── health.py # /livez, /readyz, /health endpoints
613
- ├── logging_config.py # structured JSON log setup
614
- ├── security_headers.py # HSTS, CSP, etc.
615
- ├── body_size.py # request body size guards
616
- ├── jwks.py # JWKS generation + rotation helpers
617
- ├── keyset.py # asymmetric key rotation manifest
618
- ├── secretset.py # symmetric secret rotation manifest
619
- ├── hooks.py # generic hook system: on() / fire()
620
- ├── mail.py # email send with job-retry fallback
621
- ├── auth/
622
- │ ├── schemas.py
623
- │ ├── service.py # full auth layer: signup / OAuth / OTP / recover …
624
- │ ├── router.py # all /auth/v1/* routes
625
- │ └── providers/ # Google, GitHub, OAuth2 helpers
626
- ├── storage/
627
- │ ├── backends.py # LocalBackend, S3Backend
628
- │ ├── service.py
629
- │ └── router.py # /storage/v1/*
630
- ├── functions/
631
- │ ├── loader.py # filesystem discovery + hot reload
632
- │ └── router.py # /functions/v1/*
633
- ├── realtime/
634
- │ ├── protocol.py # Phoenix Channels encode/decode
635
- │ ├── broker.py # fan-out engine with RLS filtering
636
- │ ├── websocket.py # WS route with JWT auth
637
- │ └── router.py # /realtime/v1/*
638
- ├── jobs/
639
- │ ├── registry.py # @job / @cron decorator store
640
- │ ├── service.py # enqueue, claim_next, mark_*
641
- │ ├── worker.py # long-running poll/dispatch/drain loop
642
- │ ├── cron.py # pg_cron sync + InProcScheduler
643
- │ └── router.py # /jobs/v1/*
644
- ├── admin/
645
- │ ├── session.py # admin cookie session (SHA-256 hashed, 8h TTL)
646
- │ ├── deps.py # require_admin dependency
647
- │ ├── spa.py # static SPA mount + index.html fallback
648
- │ ├── schemas.py # shared Pydantic models
649
- │ ├── audit.py # admin audit log writer
650
- │ ├── static/ # pre-built Vue 3 SPA bundle (committed)
651
- │ └── api/ # /admin/api/v1/* route handlers
652
- ├── backups/ # pg_dump wrapper + restore
653
- ├── gen/ # supython gen types --lang py|ts
654
- ├── scaffold/ # supython init templates
655
- └── client/ # Python SDK (optional [client] extra)
544
+ ├── src/supython/ # the FastAPI service + CLI (the published package)
545
+ ├── app.py # FastAPI factory
546
+ ├── cli.py # typer CLI: init, up, dev, worker, migrate, gen, …
547
+ ├── db.py # asyncpg pool + as_role() / as_service_role()
548
+ ├── settings.py # pydantic-settings, .env-driven
549
+ ├── tokens.py # RS256/ES256 JWT + JWKS
550
+ │ ├── migrate.py # ~50-line SQL migration runner
551
+ │ ├── migrations/ # framework schema (auth, storage, realtime, jobs, …)
552
+ │ ├── auth/ # /auth/v1/* — signup, OAuth, OTP, recovery
553
+ │ ├── storage/ # /storage/v1/* — local + S3 backends
554
+ ├── functions/ # /functions/v1/* — filesystem-discovered handlers
555
+ ├── realtime/ # /realtime/v1/* — Phoenix Channels over LISTEN/NOTIFY
556
+ │ ├── jobs/ # /jobs/v1/* — queue, worker, pg_cron scheduling
557
+ │ ├── admin/ # /admin/api/v1/* + the built Vue SPA (static/)
558
+ │ ├── backups/ # pg_dump wrapper + restore
559
+ │ ├── gen/ # `supython gen types --lang py|ts`
560
+ │ ├── scaffold/ # `supython init` templates
561
+ └── client/ # optional Python SDK ([client] extra)
562
+ ├── admin-ui/ # Vue 3 + Vite SPA, built → src/supython/admin/static/
563
+ ├── ts-sdk/ # @supython/sdk TypeScript SDK
564
+ ├── dev-app/ # scaffolded sample project for local development
565
+ ├── examples/ # .http smoke tests + chat.html realtime demo
566
+ ├── tests/ # unit/ (no Docker) + integration/ (Postgres :54323)
567
+ ├── Dockerfile
568
+ └── pyproject.toml
656
569
  ```
657
570
 
658
571
  ## Plugins & extensions
@@ -692,10 +605,10 @@ supython down # stop the stack (keeps data)
692
605
  supython down --prod # stop the prod stack
693
606
  supython reset # stop the stack and DELETE the volume (destructive)
694
607
  supython reset --prod # stop prod stack and DELETE volumes
695
- supython migrate # apply pending SQL migrations
608
+ supython migrate # apply supython's framework migrations (auth, storage, …)
696
609
  supython info # print resolved settings
697
610
  supython doctor # diagnose roles, extensions, JWKS, grants, migration drift
698
- supython init <name> # scaffold a new supython project
611
+ supython init <pkg> [dir] # scaffold a project (pkg = package name; dir defaults to ./<pkg>)
699
612
  supython gen types --lang py --out db_schema.py # emit typed dataclasses + TypedDicts
700
613
  supython gen types --lang ts --out types.ts # emit TypeScript Database interface
701
614
 
@@ -818,25 +731,6 @@ unit tests always run in isolation.
818
731
  **CI:** runners with Docker run `supython test up && supython test run`;
819
732
  runners without Docker run `pytest tests/unit` for a meaningful subset.
820
733
 
821
- ## Roadmap
822
-
823
- - ✅ Email/password auth, PostgREST contract, RLS demo
824
- - ✅ OAuth, password reset, magic link, OTP, reuse detection, email backend, test suite
825
- - ✅ Storage (S3/local) with RLS-on-metadata, edge-style functions from a `functions/` directory; `db.as_role(role, claims)` helper; `supython init` scaffold; `supython gen types --lang py`
826
- - ✅ Realtime over `LISTEN/NOTIFY` with RLS-aware fan-out; Phoenix Channels wire format; broadcast + presence; `examples/chat.html` demo
827
- - ✅ Job queue worker + `pg_cron` scheduling + hooks + CLI management commands
828
- - ✅ Grooming + security foundation: unified versioning, CORS closed by default, RS256 JWT, rate limiting, `supython doctor`, pool sizing, statement timeout
829
- - ✅ Production observable: structured JSON logs, `/livez`/`/readyz`/`/health`, security headers, input size guards, audit log completeness, OAuth PKCE, secret rotation runbooks
830
- - ✅ (partial) Multi-arch Docker images, admin control plane (Vue 3 SPA — database, auth, storage, functions, realtime, jobs, backups, log tail), CI buildx workflow; benchmarks + security audit pass + dependency budget CI remaining
831
- - *(deferred)* — Realtime v2 over logical replication
832
- - ✅ **TypeScript SDK** — `@supython/sdk` wrapping `@supabase/postgrest-js` + `@supabase/realtime-js`
833
-
834
- ### Future
835
-
836
- - **Admin control plane** polish (tests + remaining DoD items)
837
- - **Realtime v2** — logical replication (demand-driven; swap when trigger overhead or >8KB payload data warrants it)
838
- - **Prometheus `/metrics`** + **OpenTelemetry** — optional extras
839
-
840
734
  ## License
841
735
 
842
736
  MIT
@@ -94,20 +94,25 @@ python -m venv .venv && source .venv/bin/activate
94
94
  pip install supython
95
95
 
96
96
  # 2. scaffold a new project
97
+ # `myapp` is the importable package name. An optional second argument
98
+ # sets the target dir (`.` = current dir); it defaults to ./myapp.
97
99
  supython init myapp
98
100
  cd myapp
99
- cp .env.example .env
100
- # Review .env — at minimum confirm AUTHENTICATOR_PASSWORD matches
101
- # the value PostgREST will use (docker-compose.yml injects it via env).
101
+ # install the project (and supython, pinned in the generated pyproject.toml)
102
+ pip install -e .
102
103
  #
103
- # The scaffold creates:
104
- # manage.py Optional CLI entrypoint (sets SUPYTHON_SETTINGS_MODULE)
104
+ # The scaffold generates a ready-to-run, gitignored .env plus a JWT keypair
105
+ # and signing secrets under .supython/ no manual edits needed to boot.
106
+ # It also creates:
107
+ # pyproject.toml — declares this project, pins the supython version
105
108
  # myapp/settings.py — declare EXTENSIONS, EXTRA_ROUTERS, EXTRA_MIDDLEWARE
106
- # myapp/jobs.py example @job seed (register your background jobs here)
107
- # myapp/hooks.py example @on("signup") seed (lifecycle hooks)
109
+ # myapp/jobs/ package of @job / @cron modules (all auto-imported)
110
+ # myapp/hooks/ package of @on(...) lifecycle hooks (all auto-imported)
108
111
  # myapp/asgi.py — optional entrypoint for uvicorn/gunicorn
112
+ # functions/hello.py — example edge function (GET /functions/hello)
113
+ # migrations/0001_create_todos.sql — example app migration (apply with dbmate)
109
114
 
110
- # 3. boot Postgres + PostgREST and run migrations (one command)
115
+ # 3. boot Postgres + PostgREST and apply supython's framework migrations
111
116
  supython up
112
117
 
113
118
  # 4. run the auth/API service (separate terminal)
@@ -132,6 +137,10 @@ You should now have:
132
137
 
133
138
  ## End-to-end smoke test
134
139
 
140
+ This uses the scaffolded `todos` table, so first apply the example app migration
141
+ (`migrations/0001_create_todos.sql`) with [dbmate](https://github.com/amacneil/dbmate)
142
+ or your migration tool of choice — `supython migrate` only handles framework schemas.
143
+
135
144
  ```bash
136
145
  # sign up
137
146
  curl -sS -X POST http://localhost:8000/auth/v1/signup \
@@ -473,128 +482,31 @@ need to edit SQL.
473
482
 
474
483
  ```
475
484
  supython/
476
- ├── manage.py # optional cli entrypoint (sets SUPYTHON_SETTINGS_MODULE)
477
- ├── docker-compose.yml # Postgres + PostgREST (dev stack)
478
- ├── docker-compose.prod.yml # hardened single-host production stack
479
- ├── docker-compose.test.yml # dedicated test Postgres on port 54323
480
- ├── Caddyfile # reverse-proxy TLS for prod
481
- ├── <name>/ # your Python package
482
- │ ├── __init__.py
483
- │ ├── settings.py # project settings (EXTENSIONS, EXTRA_ROUTERS, …)
484
- │ ├── asgi.py # optional ASGI entrypoint (uvicorn <name>.asgi:app)
485
- │ ├── jobs.py # example @job seed
486
- └── hooks.py # example @on("signup") seed
487
- ├── migrations/
488
- │ ├── 0001_extensions_and_roles.sql # anon/authenticated/service_role/authenticator
489
- │ ├── 0002_auth_schema.sql # auth.users, auth.refresh_tokens, auth.uid()
490
- │ ├── 0003_demo_todos.sql # the demo table + RLS policies
491
- │ ├── 0004_auth_v0_2.sql # identities, one_time_tokens, audit_log
492
- │ ├── 0005_storage_schema.sql # storage.buckets + storage.objects
493
- ├── 0006_realtime_schema.sql # realtime schema, trigger, enable() helper
494
- ├── 0007_jobs_schema.sql # jobs queue, cron_schedules, enqueue/claim_next
495
- ├── 0008_jobs_last_error.sql # last_error column on jobs.jobs
496
- ├── 0009_auth_rate_limits.sql # auth fixed-window rate-limit counters
497
- ├── 0010_worker_heartbeat.sql # worker heartbeat for /readyz
498
- ├── 0011_admin_schema.sql # admin.admin_users, sessions, audit
499
- ├── 0012_auth_banned_until.sql # banned_until on auth.users
500
- │ ├── 0013_email_templates.sql # auth.email_templates
501
- │ ├── 0014_realtime_payload_warning.sql # >8KB payload warning counter
502
- │ └── 0015_backups_schema.sql # backups metadata
503
- ├── examples/
504
- │ ├── todos.http # HTTP smoke tests (auth + PostgREST)
505
- │ ├── storage.http # storage upload / signed URL examples
506
- │ ├── functions.http # edge-function call examples
507
- │ └── chat.html # two-browser realtime demo (vanilla JS, zero deps)
508
- ├── docs/
509
- │ ├── PROJECT.md # architecture + roadmap (single source of truth)
510
- │ ├── Installation.md # full install guide (dev, prod, managed Postgres)
511
- │ └── admin-ui/
512
- │ ├── admin-surface-plan.md # admin implementation plan + phase status
513
- │ └── admin-surface.md # admin architecture + contracts
514
- ├── tests/
515
- │ ├── conftest.py # cross-tree fixtures (keys, capturing mailer)
516
- │ ├── _keys.py # JWT-forging helpers
517
- │ ├── fixtures/ # test function modules, etc.
518
- │ ├── unit/ # pure-Python tests (~6s, no Docker)
519
- │ │ ├── test_admin_session.py
520
- │ │ ├── test_admin_service_db.py
521
- │ │ └── ...
522
- │ └── integration/ # full ASGI + Postgres on port 54323
523
- │ ├── conftest.py # pool, app, client, autouse DB cleaners
524
- │ ├── test_auth_signup_login.py
525
- │ ├── test_admin_auth.py
526
- │ ├── test_admin_auth_users.py
527
- │ ├── test_admin_db_rows.py
528
- │ ├── test_admin_jobs.py
529
- │ ├── test_admin_ops_backups.py
530
- │ ├── test_admin_storage.py
531
- │ ├── test_postgrest_rls.py
532
- │ ├── test_realtime_ws.py
533
- │ └── ...
534
- ├── admin-ui/ # Vue 3 + Vite SPA (built → src/supython/admin/static/)
535
- │ └── src/
536
- │ ├── api/ # single fetch seam
537
- │ ├── components/ # shell, data, editors, feedback
538
- │ ├── composables/ # useResource, useTable, useConfirm, useImpersonate, …
539
- │ ├── stores/ # auth, ui
540
- │ ├── views/ # Dashboard, db/, auth/, storage/, functions/, …
541
- │ └── router/
542
- └── src/supython/
543
- ├── __init__.py # single version string
544
- ├── settings.py # pydantic-settings, .env-driven
545
- ├── db.py # asyncpg pool + lifespan + as_role() / as_service_role()
546
- ├── mailer.py # ConsoleBackend / SmtpBackend
547
- ├── tokens.py # RS256/ES256 JWT + JWKS
548
- ├── passwords.py # argon2id
549
- ├── migrate.py # ~50-line SQL migration runner
550
- ├── app.py # FastAPI factory
551
- ├── cli.py # typer: up, dev, keygen, admin, worker, test, …
552
- ├── extensions.py # eager-import dotted module paths at boot
553
- ├── settings_module.py # user settings (EXTENSIONS, EXTRA_ROUTERS, …)
554
- ├── health.py # /livez, /readyz, /health endpoints
555
- ├── logging_config.py # structured JSON log setup
556
- ├── security_headers.py # HSTS, CSP, etc.
557
- ├── body_size.py # request body size guards
558
- ├── jwks.py # JWKS generation + rotation helpers
559
- ├── keyset.py # asymmetric key rotation manifest
560
- ├── secretset.py # symmetric secret rotation manifest
561
- ├── hooks.py # generic hook system: on() / fire()
562
- ├── mail.py # email send with job-retry fallback
563
- ├── auth/
564
- │ ├── schemas.py
565
- │ ├── service.py # full auth layer: signup / OAuth / OTP / recover …
566
- │ ├── router.py # all /auth/v1/* routes
567
- │ └── providers/ # Google, GitHub, OAuth2 helpers
568
- ├── storage/
569
- │ ├── backends.py # LocalBackend, S3Backend
570
- │ ├── service.py
571
- │ └── router.py # /storage/v1/*
572
- ├── functions/
573
- │ ├── loader.py # filesystem discovery + hot reload
574
- │ └── router.py # /functions/v1/*
575
- ├── realtime/
576
- │ ├── protocol.py # Phoenix Channels encode/decode
577
- │ ├── broker.py # fan-out engine with RLS filtering
578
- │ ├── websocket.py # WS route with JWT auth
579
- │ └── router.py # /realtime/v1/*
580
- ├── jobs/
581
- │ ├── registry.py # @job / @cron decorator store
582
- │ ├── service.py # enqueue, claim_next, mark_*
583
- │ ├── worker.py # long-running poll/dispatch/drain loop
584
- │ ├── cron.py # pg_cron sync + InProcScheduler
585
- │ └── router.py # /jobs/v1/*
586
- ├── admin/
587
- │ ├── session.py # admin cookie session (SHA-256 hashed, 8h TTL)
588
- │ ├── deps.py # require_admin dependency
589
- │ ├── spa.py # static SPA mount + index.html fallback
590
- │ ├── schemas.py # shared Pydantic models
591
- │ ├── audit.py # admin audit log writer
592
- │ ├── static/ # pre-built Vue 3 SPA bundle (committed)
593
- │ └── api/ # /admin/api/v1/* route handlers
594
- ├── backups/ # pg_dump wrapper + restore
595
- ├── gen/ # supython gen types --lang py|ts
596
- ├── scaffold/ # supython init templates
597
- └── client/ # Python SDK (optional [client] extra)
485
+ ├── src/supython/ # the FastAPI service + CLI (the published package)
486
+ ├── app.py # FastAPI factory
487
+ ├── cli.py # typer CLI: init, up, dev, worker, migrate, gen, …
488
+ ├── db.py # asyncpg pool + as_role() / as_service_role()
489
+ ├── settings.py # pydantic-settings, .env-driven
490
+ ├── tokens.py # RS256/ES256 JWT + JWKS
491
+ │ ├── migrate.py # ~50-line SQL migration runner
492
+ │ ├── migrations/ # framework schema (auth, storage, realtime, jobs, …)
493
+ │ ├── auth/ # /auth/v1/* — signup, OAuth, OTP, recovery
494
+ │ ├── storage/ # /storage/v1/* — local + S3 backends
495
+ ├── functions/ # /functions/v1/* — filesystem-discovered handlers
496
+ ├── realtime/ # /realtime/v1/* — Phoenix Channels over LISTEN/NOTIFY
497
+ │ ├── jobs/ # /jobs/v1/* — queue, worker, pg_cron scheduling
498
+ │ ├── admin/ # /admin/api/v1/* + the built Vue SPA (static/)
499
+ │ ├── backups/ # pg_dump wrapper + restore
500
+ │ ├── gen/ # `supython gen types --lang py|ts`
501
+ │ ├── scaffold/ # `supython init` templates
502
+ └── client/ # optional Python SDK ([client] extra)
503
+ ├── admin-ui/ # Vue 3 + Vite SPA, built → src/supython/admin/static/
504
+ ├── ts-sdk/ # @supython/sdk TypeScript SDK
505
+ ├── dev-app/ # scaffolded sample project for local development
506
+ ├── examples/ # .http smoke tests + chat.html realtime demo
507
+ ├── tests/ # unit/ (no Docker) + integration/ (Postgres :54323)
508
+ ├── Dockerfile
509
+ └── pyproject.toml
598
510
  ```
599
511
 
600
512
  ## Plugins & extensions
@@ -634,10 +546,10 @@ supython down # stop the stack (keeps data)
634
546
  supython down --prod # stop the prod stack
635
547
  supython reset # stop the stack and DELETE the volume (destructive)
636
548
  supython reset --prod # stop prod stack and DELETE volumes
637
- supython migrate # apply pending SQL migrations
549
+ supython migrate # apply supython's framework migrations (auth, storage, …)
638
550
  supython info # print resolved settings
639
551
  supython doctor # diagnose roles, extensions, JWKS, grants, migration drift
640
- supython init <name> # scaffold a new supython project
552
+ supython init <pkg> [dir] # scaffold a project (pkg = package name; dir defaults to ./<pkg>)
641
553
  supython gen types --lang py --out db_schema.py # emit typed dataclasses + TypedDicts
642
554
  supython gen types --lang ts --out types.ts # emit TypeScript Database interface
643
555
 
@@ -760,25 +672,6 @@ unit tests always run in isolation.
760
672
  **CI:** runners with Docker run `supython test up && supython test run`;
761
673
  runners without Docker run `pytest tests/unit` for a meaningful subset.
762
674
 
763
- ## Roadmap
764
-
765
- - ✅ Email/password auth, PostgREST contract, RLS demo
766
- - ✅ OAuth, password reset, magic link, OTP, reuse detection, email backend, test suite
767
- - ✅ Storage (S3/local) with RLS-on-metadata, edge-style functions from a `functions/` directory; `db.as_role(role, claims)` helper; `supython init` scaffold; `supython gen types --lang py`
768
- - ✅ Realtime over `LISTEN/NOTIFY` with RLS-aware fan-out; Phoenix Channels wire format; broadcast + presence; `examples/chat.html` demo
769
- - ✅ Job queue worker + `pg_cron` scheduling + hooks + CLI management commands
770
- - ✅ Grooming + security foundation: unified versioning, CORS closed by default, RS256 JWT, rate limiting, `supython doctor`, pool sizing, statement timeout
771
- - ✅ Production observable: structured JSON logs, `/livez`/`/readyz`/`/health`, security headers, input size guards, audit log completeness, OAuth PKCE, secret rotation runbooks
772
- - ✅ (partial) Multi-arch Docker images, admin control plane (Vue 3 SPA — database, auth, storage, functions, realtime, jobs, backups, log tail), CI buildx workflow; benchmarks + security audit pass + dependency budget CI remaining
773
- - *(deferred)* — Realtime v2 over logical replication
774
- - ✅ **TypeScript SDK** — `@supython/sdk` wrapping `@supabase/postgrest-js` + `@supabase/realtime-js`
775
-
776
- ### Future
777
-
778
- - **Admin control plane** polish (tests + remaining DoD items)
779
- - **Realtime v2** — logical replication (demand-driven; swap when trigger overhead or >8KB payload data warrants it)
780
- - **Prometheus `/metrics`** + **OpenTelemetry** — optional extras
781
-
782
675
  ## License
783
676
 
784
677
  MIT
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "supython"
7
- version = "0.1.9"
7
+ version = "0.1.11"
8
8
  description = "A lightweight Postgres-first BaaS framework for Python"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -32,6 +32,7 @@ dependencies = [
32
32
  "asyncpg>=0.30",
33
33
  "pydantic>=2.9",
34
34
  "pydantic-settings>=2.6",
35
+ "python-dotenv>=1.0",
35
36
  "email-validator>=2.2",
36
37
  "argon2-cffi>=23.1",
37
38
  "pyjwt[crypto]>=2.10",
@@ -27,7 +27,7 @@ from .body_size import BodySizeLimitMiddleware
27
27
  from .security_headers import SecurityHeadersMiddleware
28
28
  from .realtime import get_broker
29
29
  from .realtime.router import router as realtime_router
30
- from .settings import get_settings
30
+ from .settings import export_env_file, get_settings
31
31
  from .storage.router import router as storage_router
32
32
 
33
33
  logger = logging.getLogger(__name__)
@@ -96,6 +96,7 @@ async def _lifespan(app: FastAPI) -> AsyncIterator[None]:
96
96
 
97
97
 
98
98
  def create_app() -> FastAPI:
99
+ export_env_file()
99
100
  settings = get_settings()
100
101
  configure_logging(settings.log_level, json_format=settings.log_json)
101
102