mountaineer 0.4.2.dev3__tar.gz → 0.5.0.dev1__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 (265) hide show
  1. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/.gitignore +1 -0
  2. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/Cargo.lock +1 -1
  3. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/Cargo.toml +1 -1
  4. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/PKG-INFO +1 -1
  5. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/app.py +2 -0
  6. mountaineer-0.5.0.dev1/ci_webapp/ci_webapp/controllers/root_layout.py +23 -0
  7. mountaineer-0.5.0.dev1/ci_webapp/ci_webapp/views/app/layout.tsx +25 -0
  8. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/editor_configs/vim/.vimrc +3 -1
  9. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/editor_configs/vscode/.vscode/settings.json +2 -1
  10. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/.gitignore +1 -0
  11. mountaineer-0.5.0.dev1/docs_website/docs/api/controller.md +7 -0
  12. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/deploy.md +1 -0
  13. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/quickstart.md +2 -2
  14. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/views.md +77 -2
  15. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/pyproject.toml +1 -0
  16. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__init__.py +1 -0
  17. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/actions/test_fields.py +19 -4
  18. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/actions/test_passthrough.py +5 -3
  19. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/actions/test_sideeffect.py +11 -7
  20. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/client_builder/test_builder.py +49 -0
  21. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/test_app.py +26 -0
  22. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/test_cli.py +1 -1
  23. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/test_controller.py +9 -2
  24. mountaineer-0.5.0.dev1/mountaineer/__tests__/test_controller_layout.py +42 -0
  25. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/test_paths.py +1 -0
  26. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/test_ssr.py +5 -3
  27. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/actions/fields.py +23 -5
  28. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/actions/passthrough.py +2 -2
  29. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/actions/sideeffect.py +17 -5
  30. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/app.py +66 -8
  31. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/cli.py +4 -6
  32. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/client_builder/builder.py +34 -6
  33. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/controller.py +64 -12
  34. mountaineer-0.5.0.dev1/mountaineer/controller_layout.py +23 -0
  35. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/js_compiler/javascript.py +25 -3
  36. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/paths.py +14 -0
  37. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/ssr.py +4 -5
  38. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/static/api.ts +10 -5
  39. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/watch.py +1 -1
  40. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/watch_server.py +25 -5
  41. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/pyproject.toml +1 -1
  42. mountaineer-0.4.2.dev3/docs_website/docs/api/controller.md +0 -3
  43. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/.git-blame-ignore-revs +0 -0
  44. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/.gitattributes +0 -0
  45. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/.github/README_SCRIPTS.md +0 -0
  46. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/.github/poetry.lock +0 -0
  47. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/.github/pyproject.toml +0 -0
  48. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/.github/scripts/__init__.py +0 -0
  49. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/.github/scripts/__tests__/test_update_version.py +0 -0
  50. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/.github/scripts/check_dependencies.py +0 -0
  51. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/.github/scripts/update_version.py +0 -0
  52. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/.github/workflows/publish_docs.yml +0 -0
  53. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/.github/workflows/test.yml +0 -0
  54. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/.github/workflows/validate.yml +0 -0
  55. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/Dockerfile +0 -0
  56. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/LICENSE +0 -0
  57. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/Makefile +0 -0
  58. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/README.md +0 -0
  59. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/benchmarking/README.md +0 -0
  60. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/benchmarking/benchmarking/__init__.py +0 -0
  61. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/benchmarking/benchmarking/simple_render.py +0 -0
  62. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/benchmarking/poetry.lock +0 -0
  63. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/benchmarking/pyproject.toml +0 -0
  64. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/README.md +0 -0
  65. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/__init__.py +0 -0
  66. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/cli.py +0 -0
  67. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/config.py +0 -0
  68. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/controllers/__init__.py +0 -0
  69. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/controllers/complex.py +0 -0
  70. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/controllers/detail.py +0 -0
  71. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/controllers/home.py +0 -0
  72. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/controllers/stream.py +0 -0
  73. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/main.py +0 -0
  74. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/views/__init__.py +0 -0
  75. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/views/app/complex/page.tsx +0 -0
  76. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/views/app/detail/page.tsx +0 -0
  77. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/views/app/home/page.tsx +0 -0
  78. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/views/app/main.css +0 -0
  79. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/views/app/stream/page.tsx +0 -0
  80. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/views/package-lock.json +0 -0
  81. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/views/package.json +0 -0
  82. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/views/postcss.config.js +0 -0
  83. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/ci_webapp/views/tailwind.config.js +0 -0
  84. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/poetry.lock +0 -0
  85. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/ci_webapp/pyproject.toml +0 -0
  86. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/README.md +0 -0
  87. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/__init__.py +0 -0
  88. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/__tests__/__init__.py +0 -0
  89. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/__tests__/common.py +0 -0
  90. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/__tests__/test_builder.py +0 -0
  91. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/__tests__/test_cli.py +0 -0
  92. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/__tests__/test_generation.py +0 -0
  93. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/builder.py +0 -0
  94. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/cli.py +0 -0
  95. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/environments/__init__.py +0 -0
  96. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/environments/base.py +0 -0
  97. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/environments/poetry.py +0 -0
  98. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/environments/venv.py +0 -0
  99. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/external.py +0 -0
  100. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/generation.py +0 -0
  101. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/io.py +0 -0
  102. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/.zed/settings.json +0 -0
  103. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/__init__.py +0 -0
  104. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/editor_configs/zed/pyrightconfig.json +0 -0
  105. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/.env +0 -0
  106. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/README.md +0 -0
  107. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/[project_name]/__init__.py +0 -0
  108. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/[project_name]/app.py +0 -0
  109. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/[project_name]/cli.py +0 -0
  110. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/[project_name]/config.py +0 -0
  111. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/[project_name]/controllers/__init__.py +0 -0
  112. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/[project_name]/controllers/detail.py +0 -0
  113. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/[project_name]/controllers/home.py +0 -0
  114. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/[project_name]/main.py +0 -0
  115. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/[project_name]/models/__init__.py +0 -0
  116. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/[project_name]/models/detail.py +0 -0
  117. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/[project_name]/views/__init__.py +0 -0
  118. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/[project_name]/views/app/detail/page.tsx +0 -0
  119. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/[project_name]/views/app/home/page.tsx +0 -0
  120. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/[project_name]/views/app/main.css +0 -0
  121. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/[project_name]/views/package.json +0 -0
  122. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/[project_name]/views/postcss.config.js +0 -0
  123. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/[project_name]/views/tailwind.config.js +0 -0
  124. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/docker-compose.yml +0 -0
  125. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/create_mountaineer_app/templates/project/pyproject.toml +0 -0
  126. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/poetry.lock +0 -0
  127. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/create_mountaineer_app/pyproject.toml +0 -0
  128. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/.zed/settings.json +0 -0
  129. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/README.md +0 -0
  130. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/CNAME +0 -0
  131. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/api/actions.md +0 -0
  132. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/api/api_exception.md +0 -0
  133. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/api/app-controller.md +0 -0
  134. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/api/build_plugins/base.md +0 -0
  135. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/api/build_plugins/javascript.md +0 -0
  136. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/api/build_plugins/postcss.md +0 -0
  137. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/api/cli.md +0 -0
  138. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/api/config.md +0 -0
  139. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/api/core_dependencies.md +0 -0
  140. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/api/database/config.md +0 -0
  141. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/api/database/dependencies.md +0 -0
  142. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/api/logging.md +0 -0
  143. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/api/render.md +0 -0
  144. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/api/ssr.md +0 -0
  145. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/api/watch_server.md +0 -0
  146. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/client_actions.md +0 -0
  147. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/cma.md +0 -0
  148. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/database.md +0 -0
  149. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/error_handling.md +0 -0
  150. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/index.md +0 -0
  151. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/internal/core_library.md +0 -0
  152. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/links.md +0 -0
  153. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/media/final_todo_list.png +0 -0
  154. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/media/ide_typehints.png +0 -0
  155. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/media/network_debug.png +0 -0
  156. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/media/server_side_rendering.png +0 -0
  157. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/metadata.md +0 -0
  158. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/postcss.md +0 -0
  159. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/static_analysis.md +0 -0
  160. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/structure.md +0 -0
  161. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/docs/stylesheets/extra.css +0 -0
  162. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/mkdocs.yml +0 -0
  163. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/overrides/partials/footer.html +0 -0
  164. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/docs_website/poetry.lock +0 -0
  165. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/media/header.png +0 -0
  166. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/__init__.py +0 -0
  167. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/actions/__init__.py +0 -0
  168. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/client_builder/__init__.py +0 -0
  169. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/client_builder/test_build_actions.py +0 -0
  170. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/client_builder/test_build_links.py +0 -0
  171. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/client_builder/test_build_schemas.py +0 -0
  172. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/client_builder/test_typescript.py +0 -0
  173. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/common.py +0 -0
  174. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/conftest.py +0 -0
  175. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/database/__init__.py +0 -0
  176. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/database/dependencies/__init__.py +0 -0
  177. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/database/dependencies/conftest.py +0 -0
  178. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/database/dependencies/test_core.py +0 -0
  179. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/database/test_config.py +0 -0
  180. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/database/test_sqlmodel.py +0 -0
  181. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/dependencies/__init__.py +0 -0
  182. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/dependencies/test_base.py +0 -0
  183. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/fixtures/__init__.py +0 -0
  184. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/fixtures/complex_controller_ssr_with_react.js +0 -0
  185. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/fixtures/home_controller_source_map.js.map +0 -0
  186. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/fixtures/home_controller_ssr_with_react.js +0 -0
  187. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/js_compiler/__init__.py +0 -0
  188. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/js_compiler/test_javascript.py +0 -0
  189. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/js_compiler/test_postcss.py +0 -0
  190. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/js_compiler/test_source_maps.py +0 -0
  191. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/test_annotation_helpers.py +0 -0
  192. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/test_cache.py +0 -0
  193. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/test_config.py +0 -0
  194. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/test_cropper.py +0 -0
  195. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/test_exceptions.py +0 -0
  196. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/test_logging.py +0 -0
  197. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/__tests__/test_watch.py +0 -0
  198. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/actions/__init__.py +0 -0
  199. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/annotation_helpers.py +0 -0
  200. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/cache.py +0 -0
  201. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/client_builder/build_actions.py +0 -0
  202. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/client_builder/build_links.py +0 -0
  203. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/client_builder/build_schemas.py +0 -0
  204. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/client_builder/openapi.py +0 -0
  205. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/client_builder/typescript.py +0 -0
  206. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/config.py +0 -0
  207. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/console.py +0 -0
  208. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/constants.py +0 -0
  209. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/controllers/__init__.py +0 -0
  210. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/controllers/exception_controller.py +0 -0
  211. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/cropper.py +0 -0
  212. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/database/__init__.py +0 -0
  213. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/database/cli.py +0 -0
  214. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/database/config.py +0 -0
  215. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/database/dependencies/__init__.py +0 -0
  216. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/database/dependencies/core.py +0 -0
  217. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/database/sqlmodel.py +0 -0
  218. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/database/validator.py +0 -0
  219. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/dependencies/__init__.py +0 -0
  220. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/dependencies/base.py +0 -0
  221. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/dependencies/core/__init__.py +0 -0
  222. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/dependencies/core/core.py +0 -0
  223. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/exceptions.py +0 -0
  224. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/io.py +0 -0
  225. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/js_compiler/__init__.py +0 -0
  226. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/js_compiler/base.py +0 -0
  227. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/js_compiler/exceptions.py +0 -0
  228. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/js_compiler/postcss.py +0 -0
  229. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/js_compiler/source_maps.py +0 -0
  230. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/logging.py +0 -0
  231. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/py.typed +0 -0
  232. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/render.py +0 -0
  233. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/static/__init__.py +0 -0
  234. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/static/live_reload.ts +0 -0
  235. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/static/ssr_polyfills.js +0 -0
  236. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/test_utilities.py +0 -0
  237. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/views/__init__.py +0 -0
  238. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/views/core/exception/page.tsx +0 -0
  239. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/views/core/layout.tsx +0 -0
  240. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/views/core/main.css +0 -0
  241. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/views/package-lock.json +0 -0
  242. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/views/package.json +0 -0
  243. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/views/postcss.config.js +0 -0
  244. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/views/tailwind.config.js +0 -0
  245. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/mountaineer/webservice.py +0 -0
  246. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/poetry.lock +0 -0
  247. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src/benches/fixtures/complex_sourcemap_mapping.txt +0 -0
  248. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src/benches/fixtures/home_controller_ssr_with_react.js +0 -0
  249. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src/benches/fixtures/ssr_polyfill_archive.js +0 -0
  250. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src/benches/lexers_benchmark.rs +0 -0
  251. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src/benches/source_map_benchmark.rs +0 -0
  252. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src/benches/ssr_benchmark.rs +0 -0
  253. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src/errors.rs +0 -0
  254. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src/lexers.rs +0 -0
  255. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src/lib.rs +0 -0
  256. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src/logging.rs +0 -0
  257. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src/source_map.rs +0 -0
  258. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src/ssr.rs +0 -0
  259. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src/timeout.rs +0 -0
  260. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src_go/Cargo.toml +0 -0
  261. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src_go/build.rs +0 -0
  262. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src_go/go/js_build.go +0 -0
  263. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src_go/go.mod +0 -0
  264. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src_go/go.sum +0 -0
  265. {mountaineer-0.4.2.dev3 → mountaineer-0.5.0.dev1}/src_go/src/lib.rs +0 -0
@@ -173,6 +173,7 @@ test-project
173
173
  _server
174
174
  _ssr
175
175
  _static
176
+ _metadata
176
177
 
177
178
  # Ignore template files that might be used locally for testing
178
179
  # but shouldn't be added to the downstream templates
@@ -535,7 +535,7 @@ dependencies = [
535
535
 
536
536
  [[package]]
537
537
  name = "mountaineer"
538
- version = "0.4.2-dev3"
538
+ version = "0.5.0-dev1"
539
539
  dependencies = [
540
540
  "criterion",
541
541
  "deno_core_icudata",
@@ -15,7 +15,7 @@ harness = false
15
15
 
16
16
  [package]
17
17
  name = "mountaineer"
18
- version = "0.4.2-dev3"
18
+ version = "0.5.0-dev1"
19
19
  edition = "2021"
20
20
 
21
21
  [dependencies]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: mountaineer
3
- Version: 0.4.2.dev3
3
+ Version: 0.5.0.dev1
4
4
  Requires-Dist: pydantic
5
5
  Requires-Dist: fastapi
6
6
  Requires-Dist: inflection
@@ -5,6 +5,7 @@ from ci_webapp.config import AppConfig
5
5
  from ci_webapp.controllers.complex import ComplexController
6
6
  from ci_webapp.controllers.detail import DetailController
7
7
  from ci_webapp.controllers.home import HomeController
8
+ from ci_webapp.controllers.root_layout import RootLayoutController
8
9
  from ci_webapp.controllers.stream import StreamController
9
10
 
10
11
  controller = AppController(
@@ -20,3 +21,4 @@ controller.register(HomeController())
20
21
  controller.register(DetailController())
21
22
  controller.register(ComplexController())
22
23
  controller.register(StreamController())
24
+ controller.register(RootLayoutController())
@@ -0,0 +1,23 @@
1
+ from mountaineer import LayoutControllerBase, RenderBase
2
+ from mountaineer.actions import sideeffect
3
+
4
+
5
+ class RootLayoutRender(RenderBase):
6
+ layout_value: int
7
+
8
+
9
+ class RootLayoutController(LayoutControllerBase):
10
+ view_path = "/app/layout.tsx"
11
+
12
+ def __init__(self):
13
+ super().__init__()
14
+ self.layout_value = 0
15
+
16
+ def render(self) -> RootLayoutRender:
17
+ return RootLayoutRender(
18
+ layout_value=self.layout_value,
19
+ )
20
+
21
+ @sideeffect
22
+ async def increment_layout_value(self) -> None:
23
+ self.layout_value += 1
@@ -0,0 +1,25 @@
1
+ import React, { ReactNode } from "react";
2
+ import { useServer } from "./_server";
3
+
4
+ const Layout = ({ children }: { children: ReactNode }) => {
5
+ const serverState = useServer();
6
+
7
+ return (
8
+ <div className="p-6">
9
+ <h1>Layout State: {serverState.layout_value}</h1>
10
+ <div>{children}</div>
11
+ <div>
12
+ <button
13
+ className="rounded-md bg-indigo-500 p-2 text-white"
14
+ onClick={async () => {
15
+ await serverState.increment_layout_value();
16
+ }}
17
+ >
18
+ Layout increment
19
+ </button>
20
+ </div>
21
+ </div>
22
+ );
23
+ };
24
+
25
+ export default Layout;
@@ -2,7 +2,9 @@
2
2
  set wildignore+=*/_server/*
3
3
  set wildignore+=*/_ssr/*
4
4
  set wildignore+=*/_static/*
5
+ set wildignore+=*/_metadata/*
5
6
  set path-=*/_server/**
6
7
  set path-=*/_ssr/**
7
8
  set path-=*/_static/**
8
- {% endif %}
9
+ set path-=*/_metadata/**
10
+ {% endif %}
@@ -3,7 +3,8 @@
3
3
  "files.exclude": {
4
4
  "_server/": true,
5
5
  "_ssr/": true,
6
+ "_metadata/": true,
6
7
  "_static/": true
7
8
  }
8
9
  }
9
- {% endif %}
10
+ {% endif %}
@@ -13,6 +13,7 @@ node_modules
13
13
  _server
14
14
  _ssr
15
15
  _static
16
+ _metadata
16
17
  .watchdog.lock
17
18
 
18
19
  # General Python excludes
@@ -0,0 +1,7 @@
1
+ # View Controller
2
+
3
+ ::: mountaineer.controller.ControllerBase
4
+
5
+ # Layout Controller
6
+
7
+ ::: mountaineer.controller_layout.LayoutControllerBase
@@ -11,6 +11,7 @@ First, add the following to your `.dockerignore` file. This will prevent Docker
11
11
  **/_server
12
12
  **/_ssr
13
13
  **/_static
14
+ **/_metadata
14
15
  ```
15
16
 
16
17
  ### Image 1: Frontend Dependencies
@@ -294,9 +294,9 @@ export default Home;
294
294
 
295
295
  Go ahead and load it in your browser. If you open up your web tools, you can create a new Todo and see POST requests sending data to the backend and receiving the current server state. The actual data updates and merging happens internally by Mountaineer.
296
296
 
297
- ![Getting Started Final TODO App](/media/final_todo_list.png){ height="400" }
297
+ ![Getting Started Final TODO App](media/final_todo_list.png){ height="400" }
298
298
 
299
- ![Getting Started Final TODO App](/media/network_debug.png){ height="400" }
299
+ ![Getting Started Final TODO App](media/network_debug.png){ height="400" }
300
300
 
301
301
  You can use these serverState variables anywhere you'd use dynamic React state variables (useEffect, useCallback, etc). But unlike React state, these variables are automatically updated when a relevant sideeffect is triggered.
302
302
 
@@ -1,4 +1,4 @@
1
- # Frontend Views
1
+ # Frontend Views & Layouts
2
2
 
3
3
  Your React app should be initialized in the `/views` folder of your Mountaineer project. This is the directory where we look for package.json and tsconfig.json, and where esbuild looks for specific build-time overrides. In other words, the views folder should look just like your frontend application if you were building a Single-Page-App (SPA). It's just embedded within your larger Mountaineer project and rendered separately.
4
4
 
@@ -84,7 +84,82 @@ This allows you to chain layouts before rendering the final, most specific page:
84
84
  /layout.tsx
85
85
  ```
86
86
 
87
- When rendering `dashboard/home/page.tsx`, the view will be wrapped in the `app/dashboard/layout.tsx` layout alongside `app/layout.tsx`. These layouts should only provide styling. Since the use of `useServer` would be ambiguous for layouts that are rendered by multiple components, they should not contain any logic or data fetching.
87
+ When rendering `dashboard/home/page.tsx`, the view will be wrapped in the `app/dashboard/layout.tsx` layout alongside `app/layout.tsx`. These layout files will be automatically found by Mountaineer during the build process. They don't require any explicit declaration in your Python backend if you're just using them for styling.
88
+
89
+ If you need more server side power and want to define them in Python, you can add a LayoutController that backs the layout.
90
+
91
+ ## Layout Controllers
92
+
93
+ Layouts support most of the same controller logic that regular pages do. They can specify their own actions, both sideeffects and passthroughs, which will re-render the layout as required.
94
+
95
+ ```python title="/controllers/root_layout.py"
96
+ from mountaineer import LayoutControllerBase, RenderBase
97
+ from mountaineer.actions import sideeffect
98
+
99
+ class RootLayoutRender(RenderBase):
100
+ layout_value: int
101
+
102
+ class RootLayoutController(LayoutControllerBase):
103
+ view_path = "/app/layout.tsx"
104
+
105
+ def __init__(self):
106
+ super().__init__()
107
+ self.layout_value = 0
108
+
109
+ def render(self) -> RootLayoutRender:
110
+ return RootLayoutRender(
111
+ layout_value=self.layout_value,
112
+ )
113
+
114
+ @sideeffect
115
+ async def increment_layout_value(self) -> None:
116
+ self.layout_value += 1
117
+ ```
118
+
119
+ All these functions are now exposed to the frontend layout, including the link generator, state, and any actions specified.
120
+
121
+ ```typescript title="/views/app/layout.tsx"
122
+ import React, { ReactNode } from "react";
123
+ import { useServer } from "./_server";
124
+
125
+ const Layout = ({ children }: { children: ReactNode }) => {
126
+ const serverState = useServer();
127
+
128
+ return (
129
+ <div className="p-6">
130
+ <h1>Layout State: {serverState.layout_value}</h1>
131
+ <div>{children}</div>
132
+ <div>
133
+ <button
134
+ className="rounded-md bg-indigo-500 p-2 text-white"
135
+ onClick={async () => {
136
+ await serverState.increment_layout_value();
137
+ }}
138
+ >
139
+ Increase Ticker
140
+ </button>
141
+ </div>
142
+ </div>
143
+ );
144
+ };
145
+
146
+ export default Layout;
147
+ ```
148
+
149
+ Once your controller is declared, you'll need to mount your layout into the AppController like you do for regular pages.
150
+
151
+ ```python title="/app.py"
152
+ app_controller = AppController(...)
153
+ app_controller.register(RootLayoutController())
154
+ ```
155
+
156
+ In general you can implement layout controllers just like you do for pages. But since they're shared across multiple pages there are a few important differences to keep in mind:
157
+
158
+ - Layout controllers will be rendered in an isolated scope. Sideeffects in one layout controller won't affect the others.
159
+ - Dependency injections are similarly isolated. They are run in an isolated, synthetic context and not with the same dependency injection parameters that the page uses.
160
+ - Layout controllers don't modify the page signature. Query params on layouts won't be extracted, for instance.
161
+
162
+ As long as you write your layout controllers without directly referencing the page that they might be wrapping, which is the case for most layouts, you should be good to go.
88
163
 
89
164
  ## Typescript Configuration
90
165
 
@@ -4,6 +4,7 @@ version = "0.1.0"
4
4
  description = ""
5
5
  authors = ["Pierce Freeman <pierce@freeman.vc>"]
6
6
  readme = "README.md"
7
+ package-mode = false
7
8
 
8
9
  [tool.poetry.dependencies]
9
10
  python = "^3.11"
@@ -6,6 +6,7 @@ from mountaineer.actions import passthrough as passthrough, sideeffect as sideef
6
6
  from mountaineer.app import AppController as AppController
7
7
  from mountaineer.config import ConfigBase as ConfigBase
8
8
  from mountaineer.controller import ControllerBase as ControllerBase
9
+ from mountaineer.controller_layout import LayoutControllerBase as LayoutControllerBase
9
10
  from mountaineer.dependencies import CoreDependencies as CoreDependencies
10
11
  from mountaineer.exceptions import APIException as APIException
11
12
  from mountaineer.js_compiler.postcss import PostCSSBundler as PostCSSBundler
@@ -1,4 +1,4 @@
1
- from typing import AsyncIterator, Iterator, Optional, Type
1
+ from typing import AsyncIterator, Iterator, Optional, Type, cast
2
2
 
3
3
  import pytest
4
4
  from fastapi.responses import JSONResponse
@@ -15,6 +15,7 @@ from mountaineer.actions.fields import (
15
15
  get_function_metadata,
16
16
  )
17
17
  from mountaineer.actions.sideeffect import sideeffect
18
+ from mountaineer.controller import ControllerBase
18
19
  from mountaineer.render import Metadata, RenderBase
19
20
 
20
21
 
@@ -27,6 +28,11 @@ class ExamplePassthroughModel(BaseModel):
27
28
  passthrough_value_a: str
28
29
 
29
30
 
31
+ class ExampleController(ControllerBase):
32
+ async def render(self) -> None:
33
+ pass
34
+
35
+
30
36
  def basic_compare_model_fields(
31
37
  actual: dict[str, FieldInfo],
32
38
  expected: dict[str, FieldInfo],
@@ -113,8 +119,16 @@ def test_fuse_metadata_to_response_typehint(
113
119
  expected_sideeffect_fields: dict[str, FieldInfo],
114
120
  expected_passthrough_fields: dict[str, FieldInfo],
115
121
  ):
116
- fused_model = fuse_metadata_to_response_typehint(metadata, render_model)
122
+ sample_controller = ExampleController()
123
+ raw_model = fuse_metadata_to_response_typehint(
124
+ metadata, sample_controller, render_model
125
+ )
126
+
127
+ assert "ExampleController" in raw_model.model_fields.keys()
117
128
 
129
+ fused_model = cast(
130
+ BaseModel, raw_model.model_fields["ExampleController"].annotation
131
+ )
118
132
  if expected_sideeffect_fields:
119
133
  assert "sideeffect" in fused_model.model_fields.keys()
120
134
  assert fused_model.model_fields["sideeffect"].annotation
@@ -131,7 +145,7 @@ def test_fuse_metadata_to_response_typehint(
131
145
  expected_passthrough_fields,
132
146
  )
133
147
 
134
- assert fused_model.__name__ == expected_model_name
148
+ assert raw_model.__name__ == expected_model_name
135
149
 
136
150
 
137
151
  class ParentRender(RenderBase):
@@ -143,7 +157,7 @@ class ChildRender(ParentRender):
143
157
 
144
158
 
145
159
  def test_fuse_metadata_to_response_typehint_inherit_render():
146
- class ParentController(BaseModel):
160
+ class ParentController(ControllerBase):
147
161
  def render(self) -> ParentRender:
148
162
  return ParentRender(render_value_a="example")
149
163
 
@@ -157,6 +171,7 @@ def test_fuse_metadata_to_response_typehint_inherit_render():
157
171
 
158
172
  model_fused = fuse_metadata_to_response_typehint(
159
173
  get_function_metadata(ChildController.sideeffect),
174
+ ChildController(),
160
175
  ChildRender,
161
176
  )
162
177
  assert set(
@@ -100,9 +100,11 @@ async def test_can_call_passthrough():
100
100
 
101
101
  # The response payload should be the same both both sync and async endpoints
102
102
  expected_response = {
103
- "passthrough": ExamplePassthroughModel(
104
- status="success",
105
- )
103
+ "TestController": {
104
+ "passthrough": ExamplePassthroughModel(
105
+ status="success",
106
+ )
107
+ }
106
108
  }
107
109
 
108
110
  assert return_value_sync == expected_response
@@ -101,11 +101,13 @@ async def call_sideeffect_common(controller: ControllerCommon):
101
101
 
102
102
  # The response payload should be the same both both sync and async endpoints
103
103
  expected_response = {
104
- "sideeffect": ExampleRenderModel(
105
- value_a="Hello",
106
- value_b="World",
107
- ),
108
- "passthrough": None,
104
+ controller.__class__.__name__: {
105
+ "sideeffect": ExampleRenderModel(
106
+ value_a="Hello",
107
+ value_b="World",
108
+ ),
109
+ "passthrough": None,
110
+ }
109
111
  }
110
112
 
111
113
  assert return_value_sync == expected_response
@@ -277,8 +279,10 @@ def test_limit_codepath_experimental(
277
279
  elapsed = (monotonic_ns() - start) / 1e9
278
280
  assert response.status_code == 200
279
281
  assert response.json() == {
280
- "sideeffect": {
281
- "value_a": "Hello 1229",
282
+ "ExampleController": {
283
+ "sideeffect": {
284
+ "value_a": "Hello 1229",
285
+ }
282
286
  }
283
287
  }
284
288
 
@@ -8,6 +8,7 @@ import pytest
8
8
  from mountaineer.app import AppController
9
9
  from mountaineer.client_builder.builder import ClientBuilder
10
10
  from mountaineer.controller import ControllerBase
11
+ from mountaineer.controller_layout import LayoutControllerBase
11
12
 
12
13
 
13
14
  class ExampleHomeController(ControllerBase):
@@ -169,3 +170,51 @@ def test_cache_is_outdated_url_change(
169
170
  )
170
171
 
171
172
  assert builder.cache_is_outdated() is True
173
+
174
+
175
+ def test_validate_unique_paths_exact_definition(
176
+ builder: ClientBuilder,
177
+ ):
178
+ """
179
+ Two controllers can't manage the same view path.
180
+
181
+ """
182
+
183
+ class ConflictingDetailController(ControllerBase):
184
+ url = "/detail/other_url/"
185
+ view_path = "/detail/page.tsx"
186
+
187
+ def render(self) -> None:
188
+ return None
189
+
190
+ builder.app.register(ConflictingDetailController())
191
+
192
+ # Raises for the same exact view path
193
+ with pytest.raises(
194
+ ValueError, match="duplicate view paths under controller management"
195
+ ):
196
+ builder.validate_unique_paths()
197
+
198
+
199
+ def test_validate_unique_paths_conflicting_layout(
200
+ builder: ClientBuilder,
201
+ ):
202
+ """
203
+ Layouts need to be placed in their own directory. Even if the literal paths
204
+ under management are different we still need to throw a validation error.
205
+
206
+ """
207
+
208
+ class ConflictingLayoutController(LayoutControllerBase):
209
+ view_path = "/detail/layout.tsx"
210
+
211
+ def render(self) -> None:
212
+ return None
213
+
214
+ builder.app.register(ConflictingLayoutController())
215
+
216
+ # Raises for the same exact view path
217
+ with pytest.raises(
218
+ ValueError, match="duplicate view paths under controller management"
219
+ ):
220
+ builder.validate_unique_paths()
@@ -12,6 +12,7 @@ from mountaineer.app import AppController
12
12
  from mountaineer.client_builder.openapi import OpenAPIDefinition
13
13
  from mountaineer.config import ConfigBase
14
14
  from mountaineer.controller import ControllerBase
15
+ from mountaineer.controller_layout import LayoutControllerBase
15
16
  from mountaineer.exceptions import APIException
16
17
 
17
18
 
@@ -43,6 +44,26 @@ def test_requires_render_return_value():
43
44
  app.register(TestControllerWithRenderMarkup())
44
45
 
45
46
 
47
+ def test_validates_layouts_exclude_urls():
48
+ """
49
+ The app controller should reject the registration of layouts that specify
50
+ a url.
51
+
52
+ """
53
+
54
+ class TestLayoutController(LayoutControllerBase):
55
+ # Not allowed, but might typehint correctly because the ControllerBase
56
+ # superclass supports it.
57
+ url = "/layout_url"
58
+
59
+ async def render(self) -> None:
60
+ pass
61
+
62
+ app_controller = AppController(view_root=Path(""))
63
+ with pytest.raises(ValueError, match="are not directly mountable to the router"):
64
+ app_controller.register(TestLayoutController())
65
+
66
+
46
67
  def test_generate_openapi():
47
68
  class ExampleSubModel(BaseModel):
48
69
  sub_value: str
@@ -72,6 +93,7 @@ def test_generate_openapi():
72
93
  "TestExceptionActionResponse",
73
94
  "ExampleException",
74
95
  "ExampleSubModel",
96
+ "TestExceptionActionResponseRaw",
75
97
  }
76
98
 
77
99
 
@@ -133,6 +155,7 @@ def test_handle_conflicting_exception_names():
133
155
 
134
156
  assert openapi_definition.components.schemas.keys() == {
135
157
  "TestExceptionActionResponse",
158
+ "TestExceptionActionResponseRaw",
136
159
  "mountaineer.__tests__.test_1.ExampleException",
137
160
  "mountaineer.__tests__.test_2.ExampleException",
138
161
  }
@@ -199,6 +222,9 @@ def test_inherit_parent_spec():
199
222
  assert parent_controller.definition
200
223
  assert child_controller.definition
201
224
 
225
+ assert parent_controller.definition.render_router
226
+ assert child_controller.definition.render_router
227
+
202
228
  parent_routes = parent_controller.definition.render_router.routes
203
229
  child_routes = child_controller.definition.render_router.routes
204
230
 
@@ -100,7 +100,7 @@ def test_dev_thrown_exception_on_get(env_process: IsolatedEnvProcess):
100
100
  response = test_client.get("/")
101
101
  assert response.status_code == 500
102
102
  assert (
103
- '<div id="root">Passthrough: {"exception":"This is a test",'
103
+ '<div id="root">Passthrough: {"ExceptionController":{"exception":"This is a test",'
104
104
  in response.text
105
105
  )
106
106
 
@@ -2,7 +2,7 @@ from pathlib import Path
2
2
 
3
3
  import pytest
4
4
 
5
- from mountaineer.controller import ControllerBase
5
+ from mountaineer.controller import BuildMetadata, ControllerBase
6
6
  from mountaineer.render import (
7
7
  LinkAttribute,
8
8
  MetaAttribute,
@@ -196,6 +196,7 @@ def test_resolve_paths(tmp_path: Path):
196
196
  view_base = tmp_path / "views"
197
197
  ssr_base = view_base / "_ssr"
198
198
  static_base = view_base / "_static"
199
+ metadata_base = view_base / "_metadata"
199
200
 
200
201
  controller = StubController()
201
202
  assert not controller.resolve_paths(view_base)
@@ -212,12 +213,18 @@ def test_resolve_paths(tmp_path: Path):
212
213
  (ssr_base / "stub_controller.js.map").touch()
213
214
  assert not controller.resolve_paths(view_base)
214
215
 
215
- # Finally, create the static script file
216
216
  # Our hash has to be exactly 32 digits to match the regex
217
217
  static_base.mkdir()
218
218
  random_hash = "b5ecd0c4405374100d6ef93088b86898"
219
219
  (static_base / f"stub_controller-{random_hash}.js").touch()
220
220
  (static_base / f"stub_controller-{random_hash}.js.map").touch()
221
+ assert not controller.resolve_paths(view_base)
222
+
223
+ # Finally, create the metadata file
224
+ metadata_base.mkdir()
225
+ (metadata_base / "stub_controller.json").write_text(
226
+ BuildMetadata(view_path=Path()).model_dump_json()
227
+ )
221
228
  assert controller.resolve_paths(view_base)
222
229
 
223
230
  # Now ensure that the paths are correctly set
@@ -0,0 +1,42 @@
1
+ from pathlib import Path
2
+
3
+ import pytest
4
+
5
+ from mountaineer.app import AppController
6
+ from mountaineer.controller_layout import LayoutControllerBase
7
+
8
+
9
+ class ExampleLayoutController(LayoutControllerBase):
10
+ async def render(self) -> None:
11
+ pass
12
+
13
+
14
+ @pytest.mark.asyncio
15
+ async def test_disallows_direct_rendering():
16
+ """
17
+ Layouts can't be rendered directly. They're intended for use
18
+ only as pages wrappers.
19
+
20
+ """
21
+ layout_controller = ExampleLayoutController()
22
+
23
+ with pytest.raises(NotImplementedError):
24
+ await layout_controller._generate_html(global_metadata={})
25
+
26
+ with pytest.raises(NotImplementedError):
27
+ layout_controller._generate_ssr_html({})
28
+
29
+
30
+ def test_layout_registration():
31
+ """
32
+ Layout controllers must register with the AppController for them
33
+ to be used by client render controllers.
34
+
35
+ """
36
+ app_controller = AppController(view_root=Path(""))
37
+ layout_controller = ExampleLayoutController()
38
+
39
+ app_controller.register(layout_controller)
40
+ assert len(app_controller.controllers) == 1
41
+
42
+ assert app_controller.controllers[0].controller == layout_controller
@@ -143,6 +143,7 @@ def test_managed_view_paths_code_directories(tmpdir):
143
143
  assert root_path.get_managed_code_dir() == root_path / "_server"
144
144
  assert root_path.get_managed_static_dir() == root_path / "_static"
145
145
  assert root_path.get_managed_ssr_dir() == root_path / "_ssr"
146
+ assert root_path.get_managed_metadata_dir() == root_path / "_metadata"
146
147
 
147
148
  # Non-root paths should only yield the server directory
148
149
  non_root_path = root_path / "subdir"
@@ -26,7 +26,7 @@ def test_ssr_speed_baseline():
26
26
  start = monotonic_ns()
27
27
  render_ssr(
28
28
  js_contents,
29
- FakeModel(random_id=uuid4()),
29
+ FakeModel(random_id=uuid4()).model_dump(mode="json"),
30
30
  hard_timeout=1,
31
31
  )
32
32
  all_measurements.append((monotonic_ns() - start) / 1e9)
@@ -54,7 +54,9 @@ def test_ssr_timeout():
54
54
  with pytest.raises(TimeoutError):
55
55
  render_ssr(
56
56
  script=js_contents,
57
- render_data=FakeWaitDurationModel(delay_loops=5, random_id=uuid4()),
57
+ render_data=FakeWaitDurationModel(
58
+ delay_loops=5, random_id=uuid4()
59
+ ).model_dump(mode="json"),
58
60
  hard_timeout=0.5,
59
61
  )
60
62
  assert ((monotonic_ns() - start) / 1e9) < 1.0
@@ -84,7 +86,7 @@ def test_ssr_exception_context():
84
86
  try:
85
87
  render_ssr(
86
88
  script=js_contents,
87
- render_data=FakeModel(random_id=uuid4()),
89
+ render_data=FakeModel(random_id=uuid4()).model_dump(mode="json"),
88
90
  hard_timeout=0,
89
91
  )
90
92
  except V8RuntimeError as e: