framework-m-studio 0.18.0__tar.gz → 0.18.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/CHANGELOG.md +16 -1
  2. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/PKG-INFO +8 -8
  3. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/pyproject.toml +8 -8
  4. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/app.py +36 -0
  5. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/deps.py +97 -103
  6. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/new.py +4 -14
  7. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/release/cli.py +4 -4
  8. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/release/graph.py +10 -5
  9. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/release/orchestrator.py +16 -14
  10. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/routers/doctypes.py +6 -2
  11. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/routers/print.py +9 -1
  12. framework_m_studio-0.18.2/src/framework_m_studio/static/assets/index-dm-Hr_Uu.js +104 -0
  13. framework_m_studio-0.18.2/src/framework_m_studio/static/assets/rolldown-runtime-DAXXjFlN.js +1 -0
  14. framework_m_studio-0.18.2/src/framework_m_studio/static/assets/vendor-icons-BoXKNKEV.js +42 -0
  15. framework_m_studio-0.18.0/src/framework_m_studio/static/assets/vendor-react-BOMmkTcq.js → framework_m_studio-0.18.2/src/framework_m_studio/static/assets/vendor-react-CjOG4HR8.js +1 -1
  16. framework_m_studio-0.18.0/src/framework_m_studio/static/assets/vendor-tamagui-jE-K7TKU.js → framework_m_studio-0.18.2/src/framework_m_studio/static/assets/vendor-tamagui-xg1M_2HA.js +1 -1
  17. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/static/index.html +5 -5
  18. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/plugin/package.json.template +19 -19
  19. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/CHANGELOG.md +10 -1
  20. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/package.json +20 -20
  21. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/core/discovery/test_pydantic_discovery.py +23 -0
  22. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/core/test_frontend.py +2 -0
  23. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_api_routes.py +23 -0
  24. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_deps_cli.py +79 -2
  25. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_github_provider.py +74 -0
  26. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_release_cli.py +48 -0
  27. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_release_cli_more.py +1 -3
  28. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_release_graph.py +35 -0
  29. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_release_orchestrator.py +2 -2
  30. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_routes_extended.py +39 -4
  31. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_sdk_generator.py +114 -0
  32. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_visual_designer.py +14 -0
  33. framework_m_studio-0.18.0/src/framework_m_studio/static/assets/index-viorSw2T.js +0 -106
  34. framework_m_studio-0.18.0/src/framework_m_studio/static/assets/rolldown-runtime-CMxvf4Kt.js +0 -1
  35. framework_m_studio-0.18.0/src/framework_m_studio/static/assets/vendor-icons-D2zb75Z-.js +0 -42
  36. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/.gitignore +0 -0
  37. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/LICENSE +0 -0
  38. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/README.md +0 -0
  39. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/docs/api/index.md +0 -0
  40. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/docs/user-guide.md +0 -0
  41. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/__init__.py +0 -0
  42. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/aggregate_builder.py +0 -0
  43. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/__init__.py +0 -0
  44. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/codegen.py +0 -0
  45. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/constants.py +0 -0
  46. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/contrib.py +0 -0
  47. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/dev.py +0 -0
  48. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/dev_link.py +0 -0
  49. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/docs.py +0 -0
  50. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/proxy.py +0 -0
  51. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/quality.py +0 -0
  52. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/release/__init__.py +0 -0
  53. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/release/gitops.py +0 -0
  54. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/release/lockfile_sync.py +0 -0
  55. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/release/models.py +0 -0
  56. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/release/versioning.py +0 -0
  57. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/screenshots.py +0 -0
  58. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/studio.py +0 -0
  59. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/translations.py +0 -0
  60. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/utility.py +0 -0
  61. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/cli/verify.py +0 -0
  62. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/codegen/__init__.py +0 -0
  63. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/codegen/annotation_parser.py +0 -0
  64. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/codegen/generator.py +0 -0
  65. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/codegen/meta_extractor.py +0 -0
  66. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/codegen/parser.py +0 -0
  67. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/codegen/templates/__init__.py.jinja2 +0 -0
  68. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/codegen/templates/controller.py.jinja2 +0 -0
  69. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/codegen/templates/doctype.py.jinja2 +0 -0
  70. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/codegen/templates/test_doctype.py.jinja2 +0 -0
  71. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/codegen/test_generator.py +0 -0
  72. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/codegen/transformer.py +0 -0
  73. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/core/adapters/cst/mutator.py +0 -0
  74. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/core/codegen/augmentation_gen.py +0 -0
  75. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/core/discovery/pydantic.py +0 -0
  76. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/core/discovery/roles.py +0 -0
  77. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/core/frontend.py +0 -0
  78. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/core/gitops.py +0 -0
  79. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/core/repositories/fs_mx_repo.py +0 -0
  80. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/core/repositories/git_mx_repo.py +0 -0
  81. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/core/shell.py +0 -0
  82. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/data_elements.py +0 -0
  83. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/dev_config.py +0 -0
  84. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/discovery.py +0 -0
  85. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/docs/ast_parsers.py +0 -0
  86. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/docs/audit.py +0 -0
  87. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/docs/exporters.py +0 -0
  88. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/docs/formatters.py +0 -0
  89. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/docs/generator.py +0 -0
  90. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/docs/openapi.py +0 -0
  91. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/docs/screenshots.py +0 -0
  92. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/doctypes/virtual_doc_type/__init__.py +0 -0
  93. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/doctypes/virtual_doc_type/controller.py +0 -0
  94. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/doctypes/virtual_doc_type/doctype.py +0 -0
  95. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/doctypes/virtual_field/__init__.py +0 -0
  96. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/doctypes/virtual_field/controller.py +0 -0
  97. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/doctypes/virtual_field/doctype.py +0 -0
  98. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/ephemeral.py +0 -0
  99. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/git/__init__.py +0 -0
  100. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/git/adapter.py +0 -0
  101. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/git/github_provider.py +0 -0
  102. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/git/protocol.py +0 -0
  103. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/guardrail.py +0 -0
  104. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/live_preview.py +0 -0
  105. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/metadata_editor.py +0 -0
  106. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/print_adapter.py +0 -0
  107. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/protocol_scanner.py +0 -0
  108. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/py.typed +0 -0
  109. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/resources/blueprints/standard.json +0 -0
  110. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/resources/roles/crm.json +0 -0
  111. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/resources/roles/financial.json +0 -0
  112. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/resources/roles/hr.json +0 -0
  113. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/resources/roles/inventory.json +0 -0
  114. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/resources/roles/project.json +0 -0
  115. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/resources/roles/standard.json +0 -0
  116. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/routers/__init__.py +0 -0
  117. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/routers/aggregate.py +0 -0
  118. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/routers/publish.py +0 -0
  119. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/routers/roles.py +0 -0
  120. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/routers/shell.py +0 -0
  121. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/routes.py +0 -0
  122. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/schema_diff.py +0 -0
  123. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/schemas.py +0 -0
  124. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/sdk_generator.py +0 -0
  125. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/services/__init__.py +0 -0
  126. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/services/aggregate.py +0 -0
  127. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/services/doctype.py +0 -0
  128. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/services/print_service.py +0 -0
  129. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/services/publish.py +0 -0
  130. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/services/shell.py +0 -0
  131. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/services/workspace.py +0 -0
  132. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/shell_plugin_config.py +0 -0
  133. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/sidebar_config.py +0 -0
  134. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/static/.gitkeep +0 -0
  135. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/static/assets/index-D8voZ-lm.css +0 -0
  136. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/static/favicon.png +0 -0
  137. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/storage/__init__.py +0 -0
  138. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/storage/file_adapter.py +0 -0
  139. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/storage/git_api_adapter.py +0 -0
  140. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/storage/protocol.py +0 -0
  141. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/app/README.md.template +0 -0
  142. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/app/__init__.py.template +0 -0
  143. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/app/doctypes_init.py.template +0 -0
  144. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/app/pyproject.toml.template +0 -0
  145. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/doctype/__init__.py.template +0 -0
  146. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/doctype/controller.py.template +0 -0
  147. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/doctype/doctype.py.template +0 -0
  148. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/doctype/test.py.template +0 -0
  149. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/plugin/.gitignore.template +0 -0
  150. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/plugin/Dashboard.tsx.template +0 -0
  151. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/plugin/README.md.template +0 -0
  152. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/plugin/favicon.png +0 -0
  153. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/plugin/index.html.template +0 -0
  154. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/plugin/index.tsx.template +0 -0
  155. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/plugin/plugin.config.ts.template +0 -0
  156. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/plugin/theme.css.template +0 -0
  157. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/plugin/tsconfig.json.template +0 -0
  158. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/plugin/vite.config.mfe.ts.template +0 -0
  159. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/templates/plugin/vite.config.ts.template +0 -0
  160. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/visual_designer.py +0 -0
  161. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/src/framework_m_studio/workspace.py +0 -0
  162. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/.gitignore +0 -0
  163. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/.npmrc +0 -0
  164. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/Dockerfile +0 -0
  165. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/README.md +0 -0
  166. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/eslint.config.js +0 -0
  167. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/index.html +0 -0
  168. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/public/favicon.png +0 -0
  169. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/App.css +0 -0
  170. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/App.test.tsx +0 -0
  171. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/App.tsx +0 -0
  172. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/AggregateTab.test.tsx +0 -0
  173. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/AggregateTab.tsx +0 -0
  174. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/AutoForm.tsx +0 -0
  175. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/AutoTable.tsx +0 -0
  176. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/CodePreview.tsx +0 -0
  177. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/ControllerEditor.tsx +0 -0
  178. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/ERDView.tsx +0 -0
  179. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/FieldEditor.tsx +0 -0
  180. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/LayoutDesigner.tsx +0 -0
  181. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/MetaEditor.test.tsx +0 -0
  182. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/MetaEditor.tsx +0 -0
  183. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/MigrationTab.test.tsx +0 -0
  184. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/MigrationTab.tsx +0 -0
  185. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/ModuleExplorer.tsx +0 -0
  186. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/NestedEditorDrawer.tsx +0 -0
  187. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/PrintTab.test.tsx +0 -0
  188. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/PrintTab.tsx +0 -0
  189. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/PropertiesPanel.tsx +0 -0
  190. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/SandboxPreview.tsx +0 -0
  191. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/TableFieldEditor.tsx +0 -0
  192. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/breadcrumb/index.tsx +0 -0
  193. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/fields/DefaultFieldComponents.tsx +0 -0
  194. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/fields/index.ts +0 -0
  195. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/fields/resolveFieldComponent.ts +0 -0
  196. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/layout/index.tsx +0 -0
  197. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/components/menu/index.tsx +0 -0
  198. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/designer/DesignerCanvas.test.tsx +0 -0
  199. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/designer/DesignerCanvas.tsx +0 -0
  200. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/designer/components/PaletteItem.tsx +0 -0
  201. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/designer/components/SectionDropZone.tsx +0 -0
  202. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/designer/hooks/useDesignerState.ts +0 -0
  203. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/index.css +0 -0
  204. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/index.tsx +0 -0
  205. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/pages/doctypes/edit.tsx +0 -0
  206. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/pages/doctypes/index.ts +0 -0
  207. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/pages/doctypes/list.tsx +0 -0
  208. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/pages/index.ts +0 -0
  209. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/pages/prints/PrintBuilderPage.tsx +0 -0
  210. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/pages/prints/index.ts +0 -0
  211. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/pages/shell-config/ShellConfiguratorPage.tsx +0 -0
  212. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/pages/shell-config/index.ts +0 -0
  213. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/providers/ThemeContext.ts +0 -0
  214. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/providers/constants.ts +0 -0
  215. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/providers/data.ts +0 -0
  216. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/providers/theme.tsx +0 -0
  217. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/providers/useTheme.ts +0 -0
  218. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/registry/defaultComponents.ts +0 -0
  219. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/registry/fieldComponents.ts +0 -0
  220. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/registry/index.ts +0 -0
  221. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/services/mock_data.ts +0 -0
  222. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/setupTests.ts +0 -0
  223. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/utils/mockDataGenerator.ts +0 -0
  224. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/src/vite-env.d.ts +0 -0
  225. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/tsconfig.json +0 -0
  226. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/tsconfig.node.json +0 -0
  227. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/vite.config.ts +0 -0
  228. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/studio_ui/vitest.config.ts +0 -0
  229. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/cli/test_new.py +0 -0
  230. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/cli/test_verify.py +0 -0
  231. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/codegen/test_annotation_parser.py +0 -0
  232. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/codegen/test_meta_extractor.py +0 -0
  233. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/conftest.py +0 -0
  234. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/core/adapters/test_cst_mutator.py +0 -0
  235. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/core/codegen/test_augmentation_gen.py +0 -0
  236. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/core/discovery/test_role_discovery.py +0 -0
  237. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/core/repositories/test_fs_mx_repo.py +0 -0
  238. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/core/test_gitops.py +0 -0
  239. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/core/test_shell.py +0 -0
  240. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/doctypes/virtual_doc_type/test_virtual_doc_type.py +0 -0
  241. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/doctypes/virtual_field/test_virtual_field.py +0 -0
  242. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_aggregate_builder.py +0 -0
  243. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_aggregate_builder_branches.py +0 -0
  244. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_aggregate_generator.py +0 -0
  245. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_builder_shell_routes.py +0 -0
  246. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_cli.py +0 -0
  247. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_cli_openapi.py +0 -0
  248. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_cli_utility.py +0 -0
  249. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_codegen_cli.py +0 -0
  250. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_contrib_cli.py +0 -0
  251. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_core_frontend.py +0 -0
  252. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_data_elements.py +0 -0
  253. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_data_elements_extended.py +0 -0
  254. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_dev.py +0 -0
  255. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_dev_cli_coverage.py +0 -0
  256. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_dev_config.py +0 -0
  257. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_dev_link.py +0 -0
  258. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_discovery.py +0 -0
  259. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_docs_ast_parsers.py +0 -0
  260. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_docs_audit.py +0 -0
  261. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_docs_exporters.py +0 -0
  262. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_docs_generator.py +0 -0
  263. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_docs_generator_enhanced.py +0 -0
  264. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_docs_generator_extended.py +0 -0
  265. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_doctype_service_coverage.py +0 -0
  266. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_ephemeral.py +0 -0
  267. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_frontend_integration.py +0 -0
  268. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_generator.py +0 -0
  269. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_git_adapter.py +0 -0
  270. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_git_protocol.py +0 -0
  271. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_guardrail.py +0 -0
  272. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_live_preview.py +0 -0
  273. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_lockfile_sync.py +0 -0
  274. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_metadata_editor.py +0 -0
  275. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_multi_repo_workspace.py +0 -0
  276. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_new_cli.py +0 -0
  277. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_parser.py +0 -0
  278. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_print_adapter.py +0 -0
  279. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_print_router_isolated.py +0 -0
  280. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_protocol_scanner.py +0 -0
  281. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_protocol_scanner_extended.py +0 -0
  282. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_proxy.py +0 -0
  283. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_quality_cli.py +0 -0
  284. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_release_gitops.py +0 -0
  285. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_release_versioning.py +0 -0
  286. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_schema_diff.py +0 -0
  287. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_screenshot_pipeline.py +0 -0
  288. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_shell_plugin_config.py +0 -0
  289. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_sidebar_routes.py +0 -0
  290. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_storage_adapters.py +0 -0
  291. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_studio.py +0 -0
  292. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_studio_codegen_generator.py +0 -0
  293. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_studio_init.py +0 -0
  294. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_transformer.py +0 -0
  295. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_translations_cli.py +0 -0
  296. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_uimeta_routes.py +0 -0
  297. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_utility_cli.py +0 -0
  298. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_utility_cli_enhanced.py +0 -0
  299. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_workspace.py +0 -0
  300. {framework_m_studio-0.18.0 → framework_m_studio-0.18.2}/tests/test_workspace_coverage.py +0 -0
@@ -1,4 +1,19 @@
1
- ## framework-m-studio v0.18.0
1
+ ## framework-m-studio v0.18.2
2
+
3
+ ### Bug Fixes
4
+
5
+ - remove flat structure fallback from doctype cli generator (0cb29c4)
6
+ - resolve TODO comments and improve tests (f06be12)
7
+ - pin Docker service version (674f106)
8
+ - stabilize CI service tests (156684f)
9
+ - satisfy pr lint checks (d3044f0)
10
+ - stabilize screenshot pipeline (78ed7cf)
11
+ - align release cli and orchestrator with standard auth refactor (b345860)
12
+ - prevent empty dependency commits when lockfile content is unchanged (f327735)
13
+ - prevent staging ignored static assets on release (8e46578)
14
+ - sync platform dependencies in templates (72be8c1)
15
+
16
+ **framework-m-studio** v0.18.1: internal dependency bump due to **framework-m-core** update## framework-m-studio v0.18.0
2
17
 
3
18
  ### Features
4
19
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: framework-m-studio
3
- Version: 0.18.0
3
+ Version: 0.18.2
4
4
  Summary: Framework M Studio - Visual DocType Builder & Developer Tools
5
5
  Project-URL: Homepage, https://gitlab.com/castlecraft/framework-m
6
6
  Project-URL: Documentation, https://gitlab.com/castlecraft/framework-m#readme
@@ -20,23 +20,23 @@ Classifier: Typing :: Typed
20
20
  Requires-Python: >=3.12
21
21
  Requires-Dist: bandit>=1.9.4
22
22
  Requires-Dist: build>=1.5.0
23
- Requires-Dist: framework-m-core>=0.26.0
24
- Requires-Dist: framework-m>=0.14.0
23
+ Requires-Dist: framework-m-core>=0.28.0
24
+ Requires-Dist: framework-m>=0.14.2
25
25
  Requires-Dist: honcho>=2.0.0
26
26
  Requires-Dist: httpx>=0.28.1
27
- Requires-Dist: ipython>=9.14.1
27
+ Requires-Dist: ipython>=9.15.0
28
28
  Requires-Dist: jinja2>=3.1.6
29
29
  Requires-Dist: libcst>=1.8.6
30
30
  Requires-Dist: mypy>=2.1.0
31
- Requires-Dist: playwright>=1.60.0
31
+ Requires-Dist: playwright>=1.61.0
32
32
  Requires-Dist: pydantic>=2.13.4
33
33
  Requires-Dist: pytest-asyncio>=1.4.0
34
34
  Requires-Dist: pytest-cov>=7.1.0
35
- Requires-Dist: pytest>=9.1.0
35
+ Requires-Dist: pytest>=9.1.1
36
36
  Requires-Dist: python-dotenv>=1.2.2
37
- Requires-Dist: python-semantic-release>=10.5.3
37
+ Requires-Dist: python-semantic-release>=10.6.0
38
38
  Requires-Dist: pyyaml>=6.0.3
39
- Requires-Dist: ruff>=0.15.17
39
+ Requires-Dist: ruff>=0.15.20
40
40
  Requires-Dist: twine>=6.2.0
41
41
  Description-Content-Type: text/markdown
42
42
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "framework-m-studio"
3
- version = "0.18.0"
3
+ version = "0.18.2"
4
4
  description = "Framework M Studio - Visual DocType Builder & Developer Tools"
5
5
  readme = "README.md"
6
6
  license = { text = "Apache-2.0" }
@@ -21,26 +21,26 @@ classifiers = [
21
21
  ]
22
22
 
23
23
  dependencies = [
24
- "framework-m-core>=0.26.0",
25
- "framework-m>=0.14.0",
24
+ "framework-m-core>=0.28.0",
25
+ "framework-m>=0.14.2",
26
26
  # Code generation
27
27
  "libcst>=1.8.6",
28
28
  "jinja2>=3.1.6",
29
29
  # Process management for dev command
30
30
  "honcho>=2.0.0",
31
- "playwright>=1.60.0",
31
+ "playwright>=1.61.0",
32
32
  "pyyaml>=6.0.3",
33
- "ipython>=9.14.1",
33
+ "ipython>=9.15.0",
34
34
  # Developer Tooling (wrapped by Studio CLI)
35
- "pytest>=9.1.0",
35
+ "pytest>=9.1.1",
36
36
  "pytest-asyncio>=1.4.0",
37
37
  "pytest-cov>=7.1.0",
38
38
  "mypy>=2.1.0",
39
- "ruff>=0.15.17",
39
+ "ruff>=0.15.20",
40
40
  "bandit>=1.9.4",
41
41
  "httpx>=0.28.1",
42
42
  # Release tools
43
- "python-semantic-release>=10.5.3",
43
+ "python-semantic-release>=10.6.0",
44
44
  "build>=1.5.0",
45
45
  "twine>=6.2.0",
46
46
  "pydantic>=2.13.4",
@@ -24,6 +24,32 @@ from litestar.static_files import create_static_files_router
24
24
  STATIC_DIR = Path(__file__).parent / "static"
25
25
 
26
26
 
27
+ def _get_studio_locale_dirs() -> list[Path | os.PathLike[Any] | str]:
28
+ """Resolve locale directories that Studio should expose at ``/locales``.
29
+
30
+ Studio reuses shared desk/ui i18n assets that are generated into the
31
+ workspace frontend locale directory. In local dev and CI screenshot jobs,
32
+ the Studio app runs as a separate service on port 9999, so it needs to
33
+ serve those root-level locale files itself.
34
+ """
35
+ candidates: list[Path | os.PathLike[Any] | str] = []
36
+ seen: set[Path] = set()
37
+
38
+ def add_candidate(path: Path) -> None:
39
+ resolved = path.resolve()
40
+ if resolved.exists() and resolved.is_dir() and resolved not in seen:
41
+ seen.add(resolved)
42
+ candidates.append(resolved)
43
+
44
+ add_candidate(STATIC_DIR / "locales")
45
+
46
+ for base in [Path.cwd(), *Path.cwd().parents]:
47
+ add_candidate(base / "frontend" / "dist" / "locales")
48
+ add_candidate(base / "frontend" / "public" / "locales")
49
+
50
+ return candidates
51
+
52
+
27
53
  # =============================================================================
28
54
  # Studio API Routes (Health & Field Types)
29
55
  # =============================================================================
@@ -389,6 +415,16 @@ def create_app() -> Litestar:
389
415
  html_mode=False,
390
416
  )
391
417
  )
418
+ locale_dirs = _get_studio_locale_dirs()
419
+ if locale_dirs:
420
+ route_handlers.append(
421
+ create_static_files_router(
422
+ path="/locales",
423
+ directories=locale_dirs,
424
+ name="studio_locales",
425
+ html_mode=False,
426
+ )
427
+ )
392
428
 
393
429
  # We mount the serve_studio_root handler which has path="/studio" and "/studio/"
394
430
  route_handlers.append(serve_studio_root)
@@ -229,7 +229,7 @@ async def deps_upgrade_command(
229
229
  cyclopts.Parameter(name="package", help="Package to upgrade (omit for all)"),
230
230
  ] = None,
231
231
  manager: Annotated[
232
- str, cyclopts.Parameter(name="--manager", help="uv or pnpm")
232
+ str, cyclopts.Parameter(name="--manager", help="uv, pnpm, or all")
233
233
  ] = "uv",
234
234
  provider: Annotated[
235
235
  str, cyclopts.Parameter(name="--provider", help="Git provider")
@@ -267,132 +267,126 @@ async def deps_upgrade_command(
267
267
  ),
268
268
  ] = True,
269
269
  ) -> None:
270
- """Upgrade a dependency and create a merge request."""
270
+ if manager not in ["uv", "pnpm", "all"]:
271
+ CLIConsole().error(f"Unknown manager: {manager}")
272
+ return
273
+
271
274
  root_path = Path(root) if root else Path.cwd()
272
275
  final_token = (
273
- token
274
- or os.environ.get("CITADEL_CI_TOKEN")
275
- or os.environ.get("GITLAB_TOKEN")
276
- or ""
276
+ token or os.environ.get("M_CI_TOKEN") or os.environ.get("GITLAB_TOKEN") or ""
277
277
  )
278
278
  final_project_id = project_id or os.environ.get("CI_PROJECT_ID") or ""
279
279
 
280
- # Check for changes in lockfiles and git status
281
- uv_lock = root_path / "uv.lock"
282
- pnpm_lock = root_path / "pnpm-lock.yaml"
283
-
284
- uv_mtime = uv_lock.stat().st_mtime if uv_lock.exists() else 0
285
- pnpm_mtime = pnpm_lock.stat().st_mtime if pnpm_lock.exists() else 0
280
+ timestamp = datetime.now(UTC).strftime("%Y%m%d%H%M%S")
281
+ branch_name = f"deps/{manager}-{package or 'all'}-{timestamp}"
286
282
 
287
- if not package:
288
- CLIConsole().info(f"Checking for all outdated packages using {manager}...")
289
- if manager == "uv":
290
- if latest:
291
- run_cmd("uvx uv-upx upgrade run", cwd=root_path)
283
+ # Create and switch to new branch upfront
284
+ if not (dry_run or skip_branch):
285
+ run_cmd("git checkout main", cwd=root_path)
286
+ run_cmd(f"git branch -D {branch_name}", cwd=root_path, check=False)
287
+ run_cmd(f"git checkout -b {branch_name}", cwd=root_path)
288
+
289
+ managers = ["uv", "pnpm"] if manager == "all" else [manager]
290
+ any_changes = False
291
+ commits_made = False
292
+
293
+ for m in managers:
294
+ CLIConsole().info(f"Checking for updates using {m}...")
295
+ if m == "uv":
296
+ if not package:
297
+ if latest:
298
+ run_cmd("uvx uv-upx upgrade run", cwd=root_path)
299
+ else:
300
+ run_cmd("uv lock --upgrade", cwd=root_path)
292
301
  else:
293
- run_cmd("uv lock --upgrade", cwd=root_path)
294
- elif manager == "pnpm":
295
- # Capture workspace versions before pnpm strips them in v11+
296
- ws_versions = _capture_pnpm_workspace_versions(root_path)
297
- cmd = "pnpm update -r --latest" if latest else "pnpm update -r"
298
- run_cmd(cmd, cwd=root_path)
299
- # Restore the explicit workspace versions
300
- _restore_pnpm_workspace_versions(ws_versions)
301
- run_cmd("pnpm install --no-frozen-lockfile", cwd=root_path)
302
- CLIConsole().info("Running pnpm audit fix...")
303
- run_cmd("pnpm audit fix", cwd=root_path, check=False)
304
- else: # pragma: no cover
305
- CLIConsole().error(f"Unknown manager: {manager}") # pragma: no cover
306
- return # pragma: no cover
307
- package = "all"
308
- else:
309
- if manager == "uv":
310
- run_cmd(f"uv lock --upgrade-package {package}", cwd=root_path)
311
- elif manager == "pnpm":
312
- ws_versions = _capture_pnpm_workspace_versions(root_path)
313
- cmd = (
314
- f"pnpm update -r {package} --latest"
315
- if latest
316
- else f"pnpm update -r {package}"
317
- )
318
- run_cmd(cmd, cwd=root_path)
319
- _restore_pnpm_workspace_versions(ws_versions)
320
- run_cmd("pnpm install --no-frozen-lockfile", cwd=root_path)
321
- else: # pragma: no cover
322
- CLIConsole().error(f"Unknown manager: {manager}") # pragma: no cover
323
- return # pragma: no cover
324
-
325
- # Check if anything actually changed
326
- new_uv_mtime = uv_lock.stat().st_mtime if uv_lock.exists() else 0
327
- new_pnpm_mtime = pnpm_lock.stat().st_mtime if pnpm_lock.exists() else 0
328
-
329
- lock_changed = (new_uv_mtime != uv_mtime) or (new_pnpm_mtime != pnpm_mtime)
330
- git_status = run_cmd("git status --short", cwd=root_path)
331
-
332
- if not (git_status or lock_changed):
302
+ run_cmd(f"uv lock --upgrade-package {package}", cwd=root_path)
303
+ elif m == "pnpm":
304
+ if not package:
305
+ ws_versions = _capture_pnpm_workspace_versions(root_path)
306
+ cmd = "pnpm update -r --latest" if latest else "pnpm update -r"
307
+ run_cmd(cmd, cwd=root_path)
308
+ _restore_pnpm_workspace_versions(ws_versions)
309
+ run_cmd("pnpm install --no-frozen-lockfile", cwd=root_path)
310
+ CLIConsole().info("Running pnpm audit fix...")
311
+ run_cmd("pnpm audit fix", cwd=root_path, check=False)
312
+ else:
313
+ ws_versions = _capture_pnpm_workspace_versions(root_path)
314
+ cmd = (
315
+ f"pnpm update -r {package} --latest"
316
+ if latest
317
+ else f"pnpm update -r {package}"
318
+ )
319
+ run_cmd(cmd, cwd=root_path)
320
+ _restore_pnpm_workspace_versions(ws_versions)
321
+ run_cmd("pnpm install --no-frozen-lockfile", cwd=root_path)
322
+
323
+ git_status = run_cmd("git status --short", cwd=root_path)
324
+
325
+ if git_status:
326
+ any_changes = True
327
+ if dry_run or skip_branch:
328
+ if dry_run:
329
+ CLIConsole().info(f"[DRY RUN] Detected changes for {m}.")
330
+ else:
331
+ CLIConsole().success(
332
+ f"Changes applied for {m} to lockfiles. skipping branch/commit as requested."
333
+ )
334
+ else:
335
+ # Stage changes
336
+ run_cmd("git add .", cwd=root_path)
337
+ if package == "all" or not package:
338
+ mr_title = f"fix({m}): update dependencies"
339
+ body = f"Automated upgrade of all {m} dependencies.\n\nReleases: *"
340
+ else:
341
+ mr_title = f"fix({m}): update {package}"
342
+ body = f"Automated upgrade of {package}.\n\nReleases: *"
343
+
344
+ run_cmd(["git", "commit", "-m", mr_title, "-m", body], cwd=root_path)
345
+ commits_made = True
346
+ CLIConsole().success(f"Committed updates for {m}.")
347
+
348
+ if not any_changes:
349
+ if not (dry_run or skip_branch):
350
+ run_cmd("git checkout main", cwd=root_path)
351
+ run_cmd(f"git branch -D {branch_name}", cwd=root_path, check=False)
333
352
  CLIConsole().success(
334
353
  f"No changes found after updating {package or 'all'}. Skipping MR."
335
354
  )
336
355
  return
337
356
 
338
- # Discovery
339
- updated_pkgs = [package] if package != "all" else None
340
- projects = _get_workspace_projects(root_path, manager, dirs, updated_pkgs)
341
-
342
- # Resolve scopes from release-config.json for the commit message
343
- scopes = _get_scopes_from_projects(root_path, projects)
344
-
345
- # Generate commit message and discover affected projects
346
- if package == "all":
347
- mr_title = f"fix({manager}): update dependencies"
348
- body = f"Automated upgrade of all {manager} dependencies."
349
- else:
350
- mr_title = f"fix({manager}): update {package}"
351
- body = f"Automated upgrade of {package}."
352
-
353
- tags = scopes if scopes else projects
354
- if tags:
355
- releases = ", ".join(tags)
356
- body += f"\n\nReleases: {releases}"
357
-
358
- if dry_run or skip_branch:
359
- if dry_run:
360
- CLIConsole().info("[DRY RUN] Would create MR:")
361
- CLIConsole().info(f"Title: {mr_title}")
362
- CLIConsole().info(f"Body:\n{body}\n")
363
- else:
364
- CLIConsole().success(
365
- "Changes applied to lockfiles. skipping branch/commit as requested."
366
- )
367
- return
368
-
369
- # Create and switch to new branch
370
- timestamp = datetime.now(UTC).strftime("%Y%m%d%H%M%S")
371
- branch_name = f"deps/{manager}-{package or 'all'}-{timestamp}"
372
-
373
- # Check for existing branch and delete it
374
- run_cmd(f"git branch -D {branch_name}", cwd=root_path, check=False)
375
- run_cmd(f"git checkout -b {branch_name}", cwd=root_path)
376
-
377
- run_cmd("git add .", cwd=root_path)
378
-
379
- run_cmd(["git", "commit", "-m", mr_title, "-m", body], cwd=root_path)
380
-
381
- if final_token:
357
+ if commits_made and final_token:
382
358
  _push_branch(branch_name, final_token)
383
359
 
384
360
  if provider == "gitlab" and final_project_id:
385
361
  client = GitLabProvider(token=final_token, project_id=final_project_id)
362
+ if manager == "all":
363
+ mr_title = "fix(deps): update all dependencies"
364
+ body = (
365
+ "Automated upgrade of both uv and pnpm dependencies.\n\nReleases: *"
366
+ )
367
+ elif package == "all" or not package:
368
+ mr_title = f"fix({manager}): update dependencies"
369
+ body = (
370
+ f"Automated upgrade of all {manager} dependencies.\n\nReleases: *"
371
+ )
372
+ else:
373
+ mr_title = f"fix({manager}): update {package}"
374
+ body = f"Automated upgrade of {package}.\n\nReleases: *"
375
+
386
376
  await client.create_mr(
387
377
  title=mr_title,
388
378
  description=body,
389
379
  source_branch=branch_name,
390
380
  target_branch="main",
391
381
  )
392
- else:
382
+ elif not final_token and any_changes and not (dry_run or skip_branch):
393
383
  CLIConsole().error("Skipping push and MR: No token provided.")
394
384
 
395
- run_cmd("git checkout main", cwd=root_path)
385
+ if not (dry_run or skip_branch):
386
+ run_cmd("git checkout main", cwd=root_path)
387
+ if not commits_made:
388
+ run_cmd(f"git branch -D {branch_name}", cwd=root_path, check=False)
389
+ CLIConsole().success("No changes to commit. Deleted temporary branch.")
396
390
 
397
391
 
398
392
  __all__ = ["deps_app", "deps_check_command", "deps_upgrade_command"]
@@ -435,20 +435,10 @@ def new_doctype_command(
435
435
  # Use app_root (not CWD) to construct paths
436
436
  # This ensures correct paths even when running from subdirectory
437
437
  app_namespace_doctypes = app_root / "src" / detected_app / "doctypes"
438
- src_doctypes = app_root / "src" / "doctypes"
439
-
440
- if app_namespace_doctypes.exists():
441
- # Namespaced structure: src/<app>/doctypes/<doctype>/
442
- output_dir = app_namespace_doctypes / snake_name
443
- test_output_dir = app_root / "tests" / "doctypes" / snake_name
444
- elif src_doctypes.exists():
445
- # Legacy flat structure: src/doctypes/<doctype>/
446
- output_dir = src_doctypes / snake_name
447
- test_output_dir = app_root / "tests" / "doctypes" / snake_name
448
- else:
449
- # Default: create in namespaced location
450
- output_dir = app_namespace_doctypes / snake_name
451
- test_output_dir = app_root / "tests" / "doctypes" / snake_name
438
+
439
+ # Always output to namespaced location src/<app>/doctypes/
440
+ output_dir = app_namespace_doctypes / snake_name
441
+ test_output_dir = app_root / "tests" / "doctypes" / snake_name
452
442
  else:
453
443
  output_dir = Path.cwd() / snake_name
454
444
  test_output_dir = Path.cwd() / "tests" / snake_name
@@ -37,7 +37,7 @@ async def release_auto_command(
37
37
  await run_release_orchestration(
38
38
  provider=provider,
39
39
  token=token
40
- or os.environ.get("CITADEL_CI_TOKEN")
40
+ or os.environ.get("M_CI_TOKEN")
41
41
  or os.environ.get("GITLAB_TOKEN")
42
42
  or "",
43
43
  project_id=project_id or os.environ.get("CI_PROJECT_ID") or "",
@@ -118,7 +118,7 @@ def release_push_command(
118
118
  final_host = host or os.environ.get("CI_SERVER_HOST", "gitlab.com")
119
119
  final_path = project_path or os.environ.get("CI_PROJECT_PATH", "")
120
120
  final_token = (
121
- token or os.environ.get("CITADEL_CI_TOKEN") or os.environ.get("GITLAB_TOKEN")
121
+ token or os.environ.get("M_CI_TOKEN") or os.environ.get("GITLAB_TOKEN")
122
122
  )
123
123
  if dry_run:
124
124
  CLIConsole().info(
@@ -143,7 +143,7 @@ async def release_mr_command(
143
143
  ) -> None:
144
144
  """Create or update a merge request."""
145
145
  final_token = (
146
- token or os.environ.get("CITADEL_CI_TOKEN") or os.environ.get("GITLAB_TOKEN")
146
+ token or os.environ.get("M_CI_TOKEN") or os.environ.get("GITLAB_TOKEN")
147
147
  )
148
148
  final_project_id = project_id or os.environ.get("CI_PROJECT_ID")
149
149
 
@@ -175,7 +175,7 @@ async def release_tag_command(
175
175
  ) -> None:
176
176
  """Create tags and releases for updated components."""
177
177
  final_token = (
178
- token or os.environ.get("CITADEL_CI_TOKEN") or os.environ.get("GITLAB_TOKEN")
178
+ token or os.environ.get("M_CI_TOKEN") or os.environ.get("GITLAB_TOKEN")
179
179
  )
180
180
  final_project_id = project_id or os.environ.get("CI_PROJECT_ID")
181
181
  root_path = Path.cwd()
@@ -92,16 +92,21 @@ class DependencyGraph:
92
92
 
93
93
  # Find which package owns the sync target
94
94
  # A package owns it if its 'paths' contains the base of the sync file path
95
+ # Map to the package with the longest matching prefix path to avoid nested path conflicts
96
+ best_target_pkg = None
97
+ best_pkg_len = -1
95
98
  for pkg in self.config.packages:
96
99
  for p_path in pkg.paths:
97
100
  # Normalize paths for comparison
98
101
  norm_sync = Path(sync_file_path).parts
99
102
  norm_pkg = Path(p_path).parts
100
- if norm_sync[: len(norm_pkg)] == norm_pkg:
101
- target_pkg = pkg.name
102
- break
103
- if target_pkg:
104
- break
103
+ if (
104
+ norm_sync[: len(norm_pkg)] == norm_pkg
105
+ and len(norm_pkg) > best_pkg_len
106
+ ):
107
+ best_pkg_len = len(norm_pkg)
108
+ best_target_pkg = pkg.name
109
+ target_pkg = best_target_pkg
105
110
 
106
111
  if target_pkg and target_pkg != dependency:
107
112
  self.add_edge(dependency, target_pkg)
@@ -310,7 +310,7 @@ def _stage_release_files(
310
310
  valid_files.append(rel_f)
311
311
 
312
312
  if valid_files:
313
- run_cmd(["git", "add", *valid_files])
313
+ run_cmd(["git", "add", "-f", *valid_files])
314
314
 
315
315
 
316
316
  async def run_release_orchestration(
@@ -369,7 +369,7 @@ async def run_release_orchestration(
369
369
 
370
370
  if not token:
371
371
  raise ValueError(
372
- "No Git token found. Please set CITADEL_CI_TOKEN or GITLAB_TOKEN environment variable."
372
+ "No Git token found. Please set M_CI_TOKEN or GITLAB_TOKEN environment variable."
373
373
  )
374
374
  project_path = os.environ.get("CI_PROJECT_PATH", "")
375
375
  host = os.environ.get("CI_SERVER_HOST", "gitlab.com")
@@ -416,19 +416,21 @@ def lint_release_scopes(config_path: str, root: Path, base: str, head: str) -> N
416
416
  line.strip() for line in res_diff.stdout.splitlines() if line.strip()
417
417
  ]
418
418
 
419
- # 2. Map changed files to packages
419
+ # 2. Map changed files to packages (taking longest matching path to handle nested paths)
420
420
  modified_packages = []
421
- for pkg in config.packages:
422
- pkg_modified = False
423
- for path in pkg.paths:
424
- norm_path = path.strip("/") + "/"
425
- if any(
426
- f.startswith(norm_path) or f == path.strip("/") for f in changed_files
427
- ):
428
- pkg_modified = True
429
- break
430
- if pkg_modified:
431
- modified_packages.append(pkg)
421
+ for f in changed_files:
422
+ best_pkg = None
423
+ best_path_len = -1
424
+ for pkg in config.packages:
425
+ for path in pkg.paths:
426
+ norm_path = path.strip("/")
427
+ if (f == norm_path or f.startswith(norm_path + "/")) and len(
428
+ norm_path
429
+ ) > best_path_len:
430
+ best_path_len = len(norm_path)
431
+ best_pkg = pkg
432
+ if best_pkg and best_pkg not in modified_packages:
433
+ modified_packages.append(best_pkg)
432
434
 
433
435
  if not modified_packages:
434
436
  CLIConsole().success("✅ No packages modified in this range.")
@@ -67,7 +67,9 @@ class DocTypeController(Controller):
67
67
  ],
68
68
  meta=final_meta,
69
69
  )
70
- raise NotFoundException(f"DocType '{name}' not found") # pragma: no cover
70
+ from framework_m_core.interfaces.i18n import t
71
+
72
+ raise NotFoundException(str(t("DocType '{name}' not found").format(name=name)))
71
73
 
72
74
  @post("/doctypes/{name:str}")
73
75
  async def create_or_update_doctype(
@@ -126,4 +128,6 @@ class DocTypeController(Controller):
126
128
  message=f"DocType '{name}' deleted successfully", # pragma: no cover
127
129
  file_path=str(file_path), # pragma: no cover
128
130
  ) # pragma: no cover
129
- raise NotFoundException(f"DocType '{name}' not found") # pragma: no cover
131
+ from framework_m_core.interfaces.i18n import t
132
+
133
+ raise NotFoundException(str(t("DocType '{name}' not found").format(name=name)))
@@ -28,7 +28,15 @@ class PrintController(Controller):
28
28
  ) -> PrintLayoutResponse:
29
29
  target = print_service.get_print_repo_path() / doctype / f"{template_name}.html"
30
30
  if not target.exists():
31
- raise NotFoundException(f"Print template '{template_name}' not found.")
31
+ from framework_m_core.interfaces.i18n import t
32
+
33
+ raise NotFoundException(
34
+ str(
35
+ t("Print template '{template_name}' not found.").format(
36
+ template_name=template_name
37
+ )
38
+ )
39
+ )
32
40
  return PrintLayoutResponse(
33
41
  doctype=doctype,
34
42
  template_name=template_name,