rpr-cli 0.1.7__tar.gz → 0.1.9__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 (221) hide show
  1. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/PKG-INFO +1 -1
  2. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/Sample-dot-github/instructions/frontend.instructions.md +1 -0
  3. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/Sample-dot-github/instructions/setup-guide.instructions.md +4 -0
  4. rpr_cli-0.1.9/src/rpr/__init__.py +1 -0
  5. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/commands/generate/storybook.py +8 -4
  6. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/commands/generate/ui.py +6 -3
  7. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/commands/init.py +2 -2
  8. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/dependencies.py +28 -2
  9. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/instructions/frontend.instructions.md +1 -0
  10. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/instructions/setup-guide.instructions.md +4 -0
  11. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/workspace.py +28 -3
  12. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_check.py +1 -1
  13. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_generate_storybook.py +4 -3
  14. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_generate_ui.py +100 -8
  15. rpr_cli-0.1.7/src/rpr/__init__.py +0 -1
  16. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/.github/agents/story.agent.md +0 -0
  17. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/.github/workflows/publish-pypi.yml +0 -0
  18. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/.gitignore +0 -0
  19. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/CLAUDE.md +0 -0
  20. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/GEMINI.md +0 -0
  21. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/LICENSE +0 -0
  22. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/README.md +0 -0
  23. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/Sample-dot-github/instructions/all.instructions.md +0 -0
  24. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/Sample-dot-github/instructions/api.instructions.md +0 -0
  25. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/Sample-dot-github/instructions/domain.instructions.md +0 -0
  26. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/Sample-dot-github/instructions/rust-engine.instructions.md +0 -0
  27. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/Sample-dot-github/instructions/tooling-setup.instructions.md +0 -0
  28. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/Sample-dot-github/instructions/tooling.instructions.md +0 -0
  29. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/Sample-dot-github/scaffolds/README.md +0 -0
  30. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/Sample-dot-github/scaffolds/api/main.py +0 -0
  31. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/Sample-dot-github/scaffolds/domain/base-repo.md +0 -0
  32. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/Sample-dot-github/scaffolds/domain/base_entity.md +0 -0
  33. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/Sample-dot-github/scaffolds/frontend/api.service.ts +0 -0
  34. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/Sample-dot-github/scaffolds/frontend/useStateNavigation.ts +0 -0
  35. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/changelogs/mui_v9.txt +0 -0
  36. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/code-map.md +0 -0
  37. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/nx_uv_setup.md +0 -0
  38. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/patch_output.py +0 -0
  39. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/pyproject.toml +0 -0
  40. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/Cargo.lock +0 -0
  41. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/Cargo.toml +0 -0
  42. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/pyproject.toml +0 -0
  43. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/rpr_parser.pyi +0 -0
  44. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/src/config/container.rs +0 -0
  45. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/src/config/mod.rs +0 -0
  46. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/src/config/settings.rs +0 -0
  47. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/src/graph.rs +0 -0
  48. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/src/lib.rs +0 -0
  49. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/src/models/dtos/mod.rs +0 -0
  50. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/src/models/entities/mod.rs +0 -0
  51. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/src/models/entities/users.rs +0 -0
  52. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/src/models/mod.rs +0 -0
  53. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/src/parse.rs +0 -0
  54. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/src/repos/base.rs +0 -0
  55. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/src/repos/mod.rs +0 -0
  56. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/src/repos/users.rs +0 -0
  57. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/src/resolve.rs +0 -0
  58. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/src/walker.rs +0 -0
  59. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/rpr-parser/uv.lock +0 -0
  60. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/special_files.md +0 -0
  61. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/agent/__init__.py +0 -0
  62. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/agent/approval.py +0 -0
  63. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/agent/bootstrap.py +0 -0
  64. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/agent/client.py +0 -0
  65. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/agent/control.py +0 -0
  66. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/agent/mock.py +0 -0
  67. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/agent/runtime.py +0 -0
  68. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/agent/session.py +0 -0
  69. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/agent/tools/__init__.py +0 -0
  70. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/agent/tools/base.py +0 -0
  71. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/agent/tools/mutating.py +0 -0
  72. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/agent/tools/readonly.py +0 -0
  73. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/agent/tools/registry.py +0 -0
  74. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/application/__init__.py +0 -0
  75. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/application/catalog.py +0 -0
  76. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/application/chat_service.py +0 -0
  77. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/application/checks.py +0 -0
  78. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/application/cli_adapter.py +0 -0
  79. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/application/completer.py +0 -0
  80. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/application/conversation_service.py +0 -0
  81. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/application/prompt_service.py +0 -0
  82. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/application/selector.py +0 -0
  83. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/application/shell.py +0 -0
  84. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/checks/__init__.py +0 -0
  85. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/checks/base.py +0 -0
  86. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/checks/instructions.py +0 -0
  87. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/checks/packages.py +0 -0
  88. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/checks/workspace.py +0 -0
  89. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/cli.py +0 -0
  90. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/commands/__init__.py +0 -0
  91. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/commands/add.py +0 -0
  92. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/commands/chat.py +0 -0
  93. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/commands/check.py +0 -0
  94. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/commands/generate/__init__.py +0 -0
  95. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/commands/generate/api.py +0 -0
  96. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/commands/generate/domain.py +0 -0
  97. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/commands/generate/engine.py +0 -0
  98. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/commands/map.py +0 -0
  99. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/commands/refresh.py +0 -0
  100. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/commands/settings.py +0 -0
  101. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/commands/sync.py +0 -0
  102. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/context.py +0 -0
  103. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/dependency_manifest_data.py +0 -0
  104. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/generators/__init__.py +0 -0
  105. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/generators/base.py +0 -0
  106. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/generators/claude.py +0 -0
  107. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/generators/copilot.py +0 -0
  108. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/generators/cursor.py +0 -0
  109. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/generators/gemini.py +0 -0
  110. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/manifest_refresh.py +0 -0
  111. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/map/__init__.py +0 -0
  112. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/map/architecture.py +0 -0
  113. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/map/chains.py +0 -0
  114. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/map/classifier.py +0 -0
  115. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/map/coverage.py +0 -0
  116. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/map/dependencies.py +0 -0
  117. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/map/extractor.py +0 -0
  118. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/map/graph.py +0 -0
  119. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/map/output.py +0 -0
  120. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/map/responsibility.py +0 -0
  121. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/map/topology.py +0 -0
  122. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/map/walker.py +0 -0
  123. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/domain/base_entity.md +0 -0
  124. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/domain/base_repo.md +0 -0
  125. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/domain/container.md +0 -0
  126. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/domain/settings.md +0 -0
  127. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/instructions/all.instructions.md +0 -0
  128. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/instructions/api.instructions.md +0 -0
  129. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/instructions/domain.instructions.md +0 -0
  130. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/instructions/rust-engine.instructions.md +0 -0
  131. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/instructions/tooling-setup.instructions.md +0 -0
  132. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/instructions/tooling.instructions.md +0 -0
  133. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/js_special_files/fetch.service.md +0 -0
  134. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/js_special_files/sticky-navigation.md +0 -0
  135. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/special_files/domain_container.md +0 -0
  136. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/special_files/domain_settings.md +0 -0
  137. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/special_files/dto_util.md +0 -0
  138. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/special_files/encrypted_column.md +0 -0
  139. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/special_files/mapper_util.md +0 -0
  140. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/scaffolds/special_files/partial_update.md +0 -0
  141. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/templates/__init__.py +0 -0
  142. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/templates/registry.py +0 -0
  143. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/ui/__init__.py +0 -0
  144. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/ui/console.py +0 -0
  145. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/ui/markdown.py +0 -0
  146. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/ui/prompt_session.py +0 -0
  147. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/ui/renderers.py +0 -0
  148. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/src/rpr/ui/theme.py +0 -0
  149. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/README.md +0 -0
  150. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/00-bootstrap-cli.md +0 -0
  151. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/01-rpr-init.md +0 -0
  152. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/02-rpr-generate-domain.md +0 -0
  153. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/03-rpr-generate-api.md +0 -0
  154. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/04-rpr-generate-ui.md +0 -0
  155. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/05-rpr-generate-engine.md +0 -0
  156. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/06-rpr-generate-storybook.md +0 -0
  157. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/07-rpr-sync-rules.md +0 -0
  158. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/08-rpr-add-template.md +0 -0
  159. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/09-rpr-check.md +0 -0
  160. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/10-rpr-domain-config.md +0 -0
  161. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/chat/18-rpr-terminal-ui-foundation.md +0 -0
  162. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/chat/19-rpr-markdown-rendering.md +0 -0
  163. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/chat/20-rpr-chat-repl.md +0 -0
  164. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/chat/21-rpr-agent-tool-loop.md +0 -0
  165. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/chat/22-rpr-chat-tui.md +0 -0
  166. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/chat/23-rpr-chat-unified-command-shell.md +0 -0
  167. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/chat/24-rpr-async-chat-runtime-and-services.md +0 -0
  168. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/chat/25-rpr-prompt-service-and-conversation-lifecycle.md +0 -0
  169. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/chat/26-rpr-shared-command-catalog.md +0 -0
  170. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/chat/27-rpr-slash-command-selection-panel.md +0 -0
  171. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/chat/28-rpr-chat-cancellable-and-multiline-input.md +0 -0
  172. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/chat/29-rpr-file-context-selection.md +0 -0
  173. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/map/11-rpr-map-command.md +0 -0
  174. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/map/12-rpr-map-file-walker.md +0 -0
  175. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/map/13-rpr-map-rust-engine.md +0 -0
  176. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/map/13a-rpr-map-gitignore.md +0 -0
  177. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/map/14-rpr-map-graph-builder.md +0 -0
  178. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/map/15-rpr-map-analysis-bridge.md +0 -0
  179. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/map/16-rpr-map-layer-classifier.md +0 -0
  180. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/map/17-rpr-map-output.md +0 -0
  181. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/map/17a-rpr-map-directory-topology.md +0 -0
  182. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/map/17b-rpr-map-architecture-assessment.md +0 -0
  183. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/map/17c-rpr-map-representative-chains.md +0 -0
  184. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/completed/map/17d-rpr-map-multi-resolution-output.md +0 -0
  185. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/map/30-rpr-map-directory-view-and-cycle-detection.md +0 -0
  186. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/map/31-rpr-map-coupling-hotspots-and-verdict-reasoning.md +0 -0
  187. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/stories/map/32-rpr-map-dependencies-responsibilities-and-test-coverage.md +0 -0
  188. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/__init__.py +0 -0
  189. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_add.py +0 -0
  190. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_architecture.py +0 -0
  191. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_architecture_unwrapped.py +0 -0
  192. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_catalog.py +0 -0
  193. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_chat.py +0 -0
  194. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_chat_service.py +0 -0
  195. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_completer.py +0 -0
  196. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_context.py +0 -0
  197. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_generate_api.py +0 -0
  198. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_generate_domain.py +0 -0
  199. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_generate_engine.py +0 -0
  200. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_init.py +0 -0
  201. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_map.py +0 -0
  202. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_map_chains.py +0 -0
  203. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_map_classifier.py +0 -0
  204. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_map_coverage.py +0 -0
  205. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_map_dependencies.py +0 -0
  206. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_map_extractor.py +0 -0
  207. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_map_graph.py +0 -0
  208. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_map_output.py +0 -0
  209. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_map_responsibility.py +0 -0
  210. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_map_topology.py +0 -0
  211. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_map_walker.py +0 -0
  212. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_packaging.py +0 -0
  213. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_prompt_session.py +0 -0
  214. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_refresh.py +0 -0
  215. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_rpr_parser_stub.py +0 -0
  216. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_selector.py +0 -0
  217. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_settings.py +0 -0
  218. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_sync.py +0 -0
  219. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/tests/test_ui.py +0 -0
  220. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/update_output.py +0 -0
  221. {rpr_cli-0.1.7 → rpr_cli-0.1.9}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rpr-cli
3
- Version: 0.1.7
3
+ Version: 0.1.9
4
4
  Summary: RPR CLI -- React Python Rust monorepo scaffolding orchestrator
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -11,6 +11,7 @@ Use React for UI composition, TanStack Query for server-state workflows, TanStac
11
11
 
12
12
  - Use functional components.
13
13
  - Extract reusable behavior into hooks instead of duplicating component logic.
14
+ - Import the generated shared UI package through the app-scoped package name `@{name}/ui`, such as `@testapp/ui`, not `@repo/{name}-ui`.
14
15
  - Prefer a shared base API service at `src/services/base/api.service.ts` when the UI package needs centralized fetch behavior.
15
16
  - Prefer a shared `useStateNavigation` hook at `src/hooks/useStateNavigation.ts` when UI state should persist in the URL.
16
17
  - Reuse existing components, hooks, and service patterns before introducing a new abstraction.
@@ -45,6 +45,9 @@ Use this guidance when validating or changing the monorepo setup against the RPR
45
45
  - Generate React app and library projects in a way that preserves the expected Nx command surface.
46
46
  - The web app should expose at least `serve`, `build`, `lint`, `test`, and `typecheck` when those capabilities exist in the generated project.
47
47
  - The UI library should expose at least `build`, `lint`, `test`, and `typecheck`.
48
+ - Use app-scoped Node package names: `packages/node/{name}-ui` publishes as `@{name}/ui`, `apps/{name}-web` publishes as `@{name}/web`, and Storybook publishes as `@{name}/sb`.
49
+ - Import the shared UI package through `@{name}/ui`, for example `import { AppThemeProvider } from "@testapp/ui"` for a `TestApp` workspace.
50
+ - Link local Node workspace packages with relative `file:` dependency specs instead of `workspace:*`, because npm must be able to install the generated workspace without unsupported protocol errors.
48
51
  - Keep Storybook as a dedicated host project at `packages/node/sb`; do not silently repurpose the UI library as the Storybook project.
49
52
 
50
53
  ## Python Expectations
@@ -81,6 +84,7 @@ npx nx run domain:migrate -- downgrade -1
81
84
  - Project roots and import package names follow the kebab-case and snake_case rules.
82
85
  - Python projects have both `src/` and `tests/`.
83
86
  - The domain import package remains `src/{name_underscore}_domain`.
87
+ - Node imports use app-scoped package names such as `@{name}/ui`, not stale `@repo/*` aliases.
84
88
  - Storybook remains hosted in `packages/node/sb`.
85
89
  - Workspace members and workspace dependency sources are complete.
86
90
  - Generated instructions, checks, and scaffolds refer to the current contract rather than stale paths.
@@ -0,0 +1 @@
1
+ __version__ = "0.1.9"
@@ -12,7 +12,9 @@ from rpr.context import RunContext
12
12
  from rpr.dependencies import (
13
13
  ROOT_STORYBOOK_DEV_DEPENDENCIES,
14
14
  STORYBOOK_DEV_DEPENDENCIES,
15
+ storybook_host_package_name,
15
16
  storybook_package_dependencies,
17
+ ui_package_name,
16
18
  )
17
19
  from rpr.workspace import ensure_npm_workspaces, write_package_json
18
20
 
@@ -185,7 +187,7 @@ def _write_sb_package_json(ctx: RunContext, sb_root: Path, ui_pkg: str) -> None:
185
187
  ctx,
186
188
  sb_root / "package.json",
187
189
  defaults={
188
- "name": "@repo/sb",
190
+ "name": storybook_host_package_name(ui_pkg),
189
191
  "version": "0.1.0",
190
192
  "private": True,
191
193
  "type": "module",
@@ -306,7 +308,8 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
306
308
 
307
309
 
308
310
  def _write_sb_app(ctx: RunContext, src_root: Path, ui_pkg: str) -> None:
309
- content = f"""import {{ uiPackageName }} from "@repo/{ui_pkg}";
311
+ ui_import_name = ui_package_name(ui_pkg)
312
+ content = f"""import {{ uiPackageName }} from "{ui_import_name}";
310
313
 
311
314
  export const storybookHostTitle = "Storybook Host";
312
315
 
@@ -368,7 +371,8 @@ export default config;
368
371
 
369
372
 
370
373
  def _write_sb_preview(ctx: RunContext, path: Path, ui_pkg: str) -> None:
371
- content = """import { appTheme } from "@repo/__UI_PKG__";
374
+ ui_import_name = ui_package_name(ui_pkg)
375
+ content = """import { appTheme } from "__UI_IMPORT__";
372
376
  import { CssBaseline, ThemeProvider } from "@mui/material";
373
377
  import type { Preview } from "@storybook/react";
374
378
  import { Fragment, createElement } from "react";
@@ -398,7 +402,7 @@ const preview: Preview = {
398
402
  };
399
403
 
400
404
  export default preview;
401
- """.replace("__UI_PKG__", ui_pkg)
405
+ """.replace("__UI_IMPORT__", ui_import_name)
402
406
  ctx.write_file(path, content)
403
407
 
404
408
 
@@ -13,7 +13,9 @@ from rpr.dependencies import (
13
13
  UI_LIBRARY_DEPENDENCIES,
14
14
  UI_LIBRARY_DEV_DEPENDENCIES,
15
15
  WEB_APP_DEV_DEPENDENCIES,
16
+ ui_package_name,
16
17
  web_app_dependencies,
18
+ web_package_name,
17
19
  )
18
20
  from rpr.workspace import ensure_npm_workspaces, write_package_json
19
21
 
@@ -140,7 +142,7 @@ def _write_ui_package_json(ctx: RunContext, lib_root: Path, ui_pkg_name: str) ->
140
142
  ctx,
141
143
  lib_root / "package.json",
142
144
  defaults={
143
- "name": f"@repo/{ui_pkg_name}",
145
+ "name": ui_package_name(ui_pkg_name),
144
146
  "version": "0.1.0",
145
147
  "private": True,
146
148
  "main": "src/index.ts",
@@ -259,7 +261,7 @@ def _write_app_package_json(
259
261
  ctx,
260
262
  app_root / "package.json",
261
263
  defaults={
262
- "name": f"@repo/{app_name}",
264
+ "name": web_package_name(app_name),
263
265
  "version": "0.1.0",
264
266
  "private": True,
265
267
  "type": "module",
@@ -370,7 +372,8 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
370
372
 
371
373
  def _write_app_tsx(ctx: RunContext, src: Path, app_name: str, ui_pkg_name: str) -> None:
372
374
  title = app_name.replace("-", " ").title()
373
- content = f"""import {{ AppThemeProvider, uiPackageName }} from "@repo/{ui_pkg_name}";
375
+ ui_import_name = ui_package_name(ui_pkg_name)
376
+ content = f"""import {{ AppThemeProvider, uiPackageName }} from "{ui_import_name}";
374
377
 
375
378
  export const appTitle = "{title}";
376
379
 
@@ -13,7 +13,7 @@ from rich.console import Console
13
13
 
14
14
  from rpr.cli import app
15
15
  from rpr.context import RunContext
16
- from rpr.dependencies import ROOT_NODE_DEV_DEPENDENCIES
16
+ from rpr.dependencies import ROOT_NODE_DEV_DEPENDENCIES, npm_package_name
17
17
  from rpr.generators.base import SyncConfig, load_rules
18
18
  from rpr.generators.claude import generate_claude_rules
19
19
  from rpr.generators.copilot import generate_copilot_rules
@@ -438,7 +438,7 @@ def _write_root_package_json(ctx: RunContext, project_name: str) -> None:
438
438
  else:
439
439
  package = {}
440
440
 
441
- package.setdefault("name", project_name)
441
+ package["name"] = npm_package_name(project_name)
442
442
  package["private"] = True
443
443
 
444
444
  workspaces = package.get("workspaces", [])
@@ -67,9 +67,35 @@ PYO3_VERSION = MANIFEST["engine"]["pyo3"]["specifier"]
67
67
  MATURIN_SPEC = MANIFEST["engine"]["maturin"]["specifier"]
68
68
 
69
69
 
70
+ def npm_package_name(package_name: str) -> str:
71
+ normalized = package_name.replace("_", "-").lower()
72
+ normalized = re.sub(r"[^a-z0-9._-]+", "-", normalized).strip(".-")
73
+ return normalized or "package"
74
+
75
+
76
+ def scoped_package_name(scope_name: str, package_name: str) -> str:
77
+ return f"@{npm_package_name(scope_name)}/{npm_package_name(package_name)}"
78
+
79
+
80
+ def _strip_suffix(package_name: str, suffix: str) -> str:
81
+ return package_name[: -len(suffix)] if package_name.endswith(suffix) else package_name
82
+
83
+
84
+ def ui_package_name(ui_pkg_name: str) -> str:
85
+ return scoped_package_name(_strip_suffix(ui_pkg_name, "-ui"), "ui")
86
+
87
+
88
+ def web_package_name(app_name: str) -> str:
89
+ return scoped_package_name(_strip_suffix(app_name, "-web"), "web")
90
+
91
+
92
+ def storybook_host_package_name(ui_pkg_name: str) -> str:
93
+ return scoped_package_name(_strip_suffix(ui_pkg_name, "-ui"), "sb")
94
+
95
+
70
96
  def web_app_dependencies(ui_pkg_name: str) -> dict[str, str]:
71
97
  return {
72
- f"@repo/{ui_pkg_name}": "workspace:*",
98
+ ui_package_name(ui_pkg_name): f"file:../../packages/node/{ui_pkg_name}",
73
99
  "react": UI_LIBRARY_DEPENDENCIES["react"],
74
100
  "react-dom": UI_LIBRARY_DEPENDENCIES["react-dom"],
75
101
  }
@@ -77,7 +103,7 @@ def web_app_dependencies(ui_pkg_name: str) -> dict[str, str]:
77
103
 
78
104
  def storybook_package_dependencies(ui_pkg_name: str) -> dict[str, str]:
79
105
  return {
80
- f"@repo/{ui_pkg_name}": "workspace:*",
106
+ ui_package_name(ui_pkg_name): f"file:../{ui_pkg_name}",
81
107
  **STORYBOOK_DEPENDENCIES,
82
108
  }
83
109
 
@@ -11,6 +11,7 @@ Use React for UI composition, TanStack Query for server-state workflows, TanStac
11
11
 
12
12
  - Use functional components.
13
13
  - Extract reusable behavior into hooks instead of duplicating component logic.
14
+ - Import the generated shared UI package through the app-scoped package name `@{name}/ui`, such as `@testapp/ui`, not `@repo/{name}-ui`.
14
15
  - Prefer a shared base API service at `src/services/base/api.service.ts` when the UI package needs centralized fetch behavior.
15
16
  - Prefer a shared `useStateNavigation` hook at `src/hooks/useStateNavigation.ts` when UI state should persist in the URL.
16
17
  - Reuse existing components, hooks, and service patterns before introducing a new abstraction.
@@ -45,6 +45,9 @@ Use this guidance when validating or changing the monorepo setup against the RPR
45
45
  - Generate React app and library projects in a way that preserves the expected Nx command surface.
46
46
  - The web app should expose at least `serve`, `build`, `lint`, `test`, and `typecheck` when those capabilities exist in the generated project.
47
47
  - The UI library should expose at least `build`, `lint`, `test`, and `typecheck`.
48
+ - Use app-scoped Node package names: `packages/node/{name}-ui` publishes as `@{name}/ui`, `apps/{name}-web` publishes as `@{name}/web`, and Storybook publishes as `@{name}/sb`.
49
+ - Import the shared UI package through `@{name}/ui`, for example `import { AppThemeProvider } from "@testapp/ui"` for a `TestApp` workspace.
50
+ - Link local Node workspace packages with relative `file:` dependency specs instead of `workspace:*`, because npm must be able to install the generated workspace without unsupported protocol errors.
48
51
  - Keep Storybook as a dedicated host project at `packages/node/sb`; do not silently repurpose the UI library as the Storybook project.
49
52
 
50
53
  ## Python Expectations
@@ -81,6 +84,7 @@ npx nx run domain:migrate -- downgrade -1
81
84
  - Project roots and import package names follow the kebab-case and snake_case rules.
82
85
  - Python projects have both `src/` and `tests/`.
83
86
  - The domain import package remains `src/{name_underscore}_domain`.
87
+ - Node imports use app-scoped package names such as `@{name}/ui`, not stale `@repo/*` aliases.
84
88
  - Storybook remains hosted in `packages/node/sb`.
85
89
  - Workspace members and workspace dependency sources are complete.
86
90
  - Generated instructions, checks, and scaffolds refer to the current contract rather than stale paths.
@@ -12,6 +12,12 @@ console = Console()
12
12
  DEFAULT_NPM_WORKSPACES = ["apps/*", "packages/node/*"]
13
13
 
14
14
 
15
+ def _npm_package_name(package_name: str) -> str:
16
+ normalized = package_name.replace("_", "-").lower()
17
+ normalized = re.sub(r"[^a-z0-9._-]+", "-", normalized).strip(".-")
18
+ return normalized or "package"
19
+
20
+
15
21
  def add_workspace_member(ctx: RunContext, member: str) -> None:
16
22
  """Add a UV workspace member to the root pyproject.toml."""
17
23
  pyproject_path = ctx.project_dir / "pyproject.toml"
@@ -76,7 +82,10 @@ def write_package_json(
76
82
  package = {}
77
83
 
78
84
  for key, value in (defaults or {}).items():
79
- package.setdefault(key, value)
85
+ if key == "name":
86
+ package[key] = value
87
+ else:
88
+ package.setdefault(key, value)
80
89
 
81
90
  for field_name, additions in (
82
91
  ("dependencies", dependencies or {}),
@@ -87,7 +96,23 @@ def write_package_json(
87
96
  field = {}
88
97
  package[field_name] = field
89
98
  for dep_name, version in additions.items():
90
- field.setdefault(dep_name, version)
99
+ if version.startswith("file:"):
100
+ for existing_name, existing_value in list(field.items()):
101
+ if (
102
+ existing_name != dep_name
103
+ and isinstance(existing_value, str)
104
+ and existing_value.startswith("workspace:")
105
+ ):
106
+ field.pop(existing_name)
107
+ existing_version = field.get(dep_name)
108
+ if existing_version is None:
109
+ field[dep_name] = version
110
+ elif (
111
+ isinstance(existing_version, str)
112
+ and existing_version.startswith("workspace:")
113
+ and version.startswith("file:")
114
+ ):
115
+ field[dep_name] = version
91
116
 
92
117
  content = json.dumps(package, indent=2) + "\n"
93
118
  if existed:
@@ -111,7 +136,7 @@ def ensure_npm_workspaces(ctx: RunContext, *, package_name: str | None = None) -
111
136
  package = {}
112
137
 
113
138
  if package_name:
114
- package.setdefault("name", package_name)
139
+ package["name"] = _npm_package_name(package_name)
115
140
  package["private"] = True
116
141
 
117
142
  workspaces = package.get("workspaces", [])
@@ -205,7 +205,7 @@ def _create_packages(base: Path) -> None:
205
205
  json.dumps(
206
206
  {
207
207
  "dependencies": {
208
- "@repo/my-app-ui": web_app_dependencies("my-app-ui")["@repo/my-app-ui"],
208
+ "@my-app/ui": web_app_dependencies("my-app-ui")["@my-app/ui"],
209
209
  **STORYBOOK_DEPENDENCIES,
210
210
  },
211
211
  "devDependencies": STORYBOOK_DEV_DEPENDENCIES,
@@ -83,7 +83,8 @@ def test_generate_storybook_scaffolds_host_package_and_starter_story(monkeypatch
83
83
  root_package["devDependencies"]["@nx/storybook"]
84
84
  == ROOT_STORYBOOK_DEV_DEPENDENCIES["@nx/storybook"]
85
85
  )
86
- assert sb_package["dependencies"]["@repo/my-app-ui"] == "workspace:*"
86
+ assert sb_package["name"] == "@my-app/sb"
87
+ assert sb_package["dependencies"]["@my-app/ui"] == "file:../my-app-ui"
87
88
  assert (
88
89
  sb_package["dependencies"]["@mui/material"]
89
90
  == storybook_package_dependencies("my-app-ui")["@mui/material"]
@@ -97,7 +98,7 @@ def test_generate_storybook_scaffolds_host_package_and_starter_story(monkeypatch
97
98
  assert "../../my-app-ui/src/**/*.stories.@(ts|tsx)" in sb_main
98
99
  assert "@storybook/addon-essentials" in sb_main
99
100
  assert "ThemeProvider" in sb_preview
100
- assert 'import { appTheme } from "@repo/my-app-ui";' in sb_preview
101
+ assert 'import { appTheme } from "@my-app/ui";' in sb_preview
101
102
  assert "createTheme" not in sb_preview
102
103
  assert 'title: "my-app-ui/Example"' in starter_story
103
104
  assert 'import { uiPackageName } from "../index";' in starter_story
@@ -201,7 +202,7 @@ def test_generate_storybook_dry_run_previews_files_and_forwards_nx_dry_run(
201
202
  assert "Would install npm dependencies for workspace root" in output
202
203
  assert "dev=[@nx/storybook]" in output
203
204
  assert "Would install npm dependencies for packages/node/sb" in output
204
- assert "runtime=[@repo/my-app-ui, @emotion/react, @emotion/styled, @mui/material, react, react-dom]" in output
205
+ assert "runtime=[@my-app/ui, @emotion/react, @emotion/styled, @mui/material, react, react-dom]" in output
205
206
  assert not Path("package.json").exists()
206
207
  assert not Path("packages/node/sb").exists()
207
208
  assert not Path(
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from contextlib import chdir
3
4
  import json
4
5
  import subprocess
5
6
  from pathlib import Path
@@ -12,6 +13,7 @@ from rpr.dependencies import (
12
13
  UI_LIBRARY_DEPENDENCIES,
13
14
  UI_LIBRARY_DEV_DEPENDENCIES,
14
15
  WEB_APP_DEV_DEPENDENCIES,
16
+ web_app_dependencies,
15
17
  )
16
18
 
17
19
 
@@ -70,8 +72,10 @@ def test_generate_ui_scaffolds_eslint_and_typecheck(monkeypatch):
70
72
  lib_project["targets"]["typecheck"]["options"]["command"]
71
73
  == "npx tsc --noEmit"
72
74
  )
73
- assert app_package["dependencies"]["@repo/my-app-ui"] == "workspace:*"
74
- assert app_package["name"] == "@repo/my-app-web"
75
+ assert app_package["dependencies"]["@my-app/ui"] == (
76
+ "file:../../packages/node/my-app-ui"
77
+ )
78
+ assert app_package["name"] == "@my-app/web"
75
79
  assert app_package["devDependencies"]["vitest"] == WEB_APP_DEV_DEPENDENCIES["vitest"]
76
80
  assert app_project["targets"]["serve"]["options"]["command"] == "npx vite"
77
81
  assert app_project["targets"]["build"]["options"]["command"] == "npx vite build"
@@ -95,7 +99,7 @@ def test_generate_ui_scaffolds_eslint_and_typecheck(monkeypatch):
95
99
  assert Path("apps/my-app-web/src/App.test.ts").exists()
96
100
  app_tsx = Path("apps/my-app-web/src/App.tsx").read_text()
97
101
  assert (
98
- 'import { AppThemeProvider, uiPackageName } from "@repo/my-app-ui";'
102
+ 'import { AppThemeProvider, uiPackageName } from "@my-app/ui";'
99
103
  in app_tsx
100
104
  )
101
105
  assert "<AppThemeProvider>" in app_tsx
@@ -133,7 +137,7 @@ def test_generate_ui_dry_run_previews_files_and_skips_install(monkeypatch, capsy
133
137
  assert "Would install npm dependencies for packages/node/my-app-ui" in output
134
138
  assert "runtime=[@mui/material, @emotion/react, @emotion/styled, @tanstack/react-query, @tanstack/react-router, react, react-dom]" in output
135
139
  assert "Would install npm dependencies for apps/my-app-web" in output
136
- assert "runtime=[@repo/my-app-ui, react, react-dom]" in output
140
+ assert "runtime=[@my-app/ui, react, react-dom]" in output
137
141
  assert recorded_calls == []
138
142
  assert not Path("package.json").exists()
139
143
  assert not Path("packages/node/my-app-ui/package.json").exists()
@@ -157,7 +161,7 @@ def test_generate_ui_preserves_existing_package_versions(monkeypatch):
157
161
  (lib_root / "package.json").write_text(
158
162
  json.dumps(
159
163
  {
160
- "name": "@repo/my-app-ui",
164
+ "name": "@my-app/ui",
161
165
  "dependencies": {
162
166
  "@tanstack/react-query": "^5.99.0",
163
167
  "zod": "^3.0.0",
@@ -168,9 +172,9 @@ def test_generate_ui_preserves_existing_package_versions(monkeypatch):
168
172
  (app_root / "package.json").write_text(
169
173
  json.dumps(
170
174
  {
171
- "name": "@repo/my-app-web",
175
+ "name": "@my-app/web",
172
176
  "dependencies": {
173
- "@repo/my-app-ui": "workspace:*",
177
+ "@my-app/ui": "workspace:*",
174
178
  "react": "^19.1.0",
175
179
  },
176
180
  }
@@ -190,6 +194,94 @@ def test_generate_ui_preserves_existing_package_versions(monkeypatch):
190
194
  == UI_LIBRARY_DEPENDENCIES["@mui/material"]
191
195
  )
192
196
  assert app_package["dependencies"]["react"] == "^19.1.0"
193
- assert app_package["dependencies"]["@repo/my-app-ui"] == "workspace:*"
197
+ assert app_package["dependencies"]["@my-app/ui"] == (
198
+ "file:../../packages/node/my-app-ui"
199
+ )
194
200
  assert app_package["devDependencies"]["vite"] == WEB_APP_DEV_DEPENDENCIES["vite"]
195
201
  assert app_package["devDependencies"]["vitest"] == WEB_APP_DEV_DEPENDENCIES["vitest"]
202
+
203
+
204
+ def test_generate_ui_normalizes_npm_package_names_for_mixed_case_app(monkeypatch):
205
+ def fake_run_command(
206
+ self, cmd, *, cwd=None, env=None, capture=False, supports_dry_run=False
207
+ ):
208
+ return _completed(cmd)
209
+
210
+ monkeypatch.setattr("rpr.context.RunContext.run_command", fake_run_command)
211
+
212
+ with runner.isolated_filesystem():
213
+ Path("TestApp").mkdir()
214
+ with chdir("TestApp"):
215
+ result = runner.invoke(app, ["generate", "ui", "TestApp"])
216
+ assert result.exit_code == 0, result.stdout
217
+
218
+ root_package = json.loads(Path("package.json").read_text())
219
+ lib_package = json.loads(
220
+ Path("packages/node/TestApp-ui/package.json").read_text()
221
+ )
222
+ app_package = json.loads(Path("apps/TestApp-web/package.json").read_text())
223
+ app_tsx = Path("apps/TestApp-web/src/App.tsx").read_text()
224
+
225
+ assert root_package["name"] == "testapp"
226
+ assert lib_package["name"] == "@testapp/ui"
227
+ assert app_package["name"] == "@testapp/web"
228
+ assert app_package["dependencies"]["@testapp/ui"] == (
229
+ "file:../../packages/node/TestApp-ui"
230
+ )
231
+ assert "workspace:*" not in json.dumps(app_package)
232
+ assert 'from "@testapp/ui"' in app_tsx
233
+ assert web_app_dependencies("TestApp-ui")["@testapp/ui"] == (
234
+ "file:../../packages/node/TestApp-ui"
235
+ )
236
+
237
+
238
+ def test_generate_ui_repairs_existing_workspace_protocol_for_mixed_case_app(
239
+ monkeypatch,
240
+ ):
241
+ def fake_run_command(
242
+ self, cmd, *, cwd=None, env=None, capture=False, supports_dry_run=False
243
+ ):
244
+ return _completed(cmd)
245
+
246
+ monkeypatch.setattr("rpr.context.RunContext.run_command", fake_run_command)
247
+
248
+ with runner.isolated_filesystem():
249
+ Path("TestApp").mkdir()
250
+ with chdir("TestApp"):
251
+ lib_root = Path("packages/node/TestApp-ui")
252
+ app_root = Path("apps/TestApp-web")
253
+ lib_root.mkdir(parents=True)
254
+ app_root.mkdir(parents=True)
255
+ Path("package.json").write_text(
256
+ json.dumps({"name": "TestApp", "private": True})
257
+ )
258
+ (lib_root / "package.json").write_text(
259
+ json.dumps({"name": "@repo/TestApp-ui", "private": True})
260
+ )
261
+ (app_root / "package.json").write_text(
262
+ json.dumps(
263
+ {
264
+ "name": "@repo/TestApp-web",
265
+ "dependencies": {
266
+ "@repo/TestApp-ui": "workspace:*",
267
+ },
268
+ }
269
+ )
270
+ )
271
+
272
+ result = runner.invoke(app, ["generate", "ui", "TestApp"])
273
+ assert result.exit_code == 0, result.stdout
274
+
275
+ root_package = json.loads(Path("package.json").read_text())
276
+ lib_package = json.loads((lib_root / "package.json").read_text())
277
+ app_package = json.loads((app_root / "package.json").read_text())
278
+
279
+ assert root_package["name"] == "testapp"
280
+ assert lib_package["name"] == "@testapp/ui"
281
+ assert app_package["name"] == "@testapp/web"
282
+ assert app_package["dependencies"] == {
283
+ "@testapp/ui": "file:../../packages/node/TestApp-ui",
284
+ "react": UI_LIBRARY_DEPENDENCIES["react"],
285
+ "react-dom": UI_LIBRARY_DEPENDENCIES["react-dom"],
286
+ }
287
+ assert "workspace:*" not in json.dumps(app_package)
@@ -1 +0,0 @@
1
- __version__ = "0.1.7"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes