rpr-cli 0.1.28__tar.gz → 0.1.30__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.
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/PKG-INFO +2 -1
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/README.md +1 -0
- rpr_cli-0.1.30/src/rpr/__init__.py +1 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/commands/generate/domain.py +6 -1
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/context.py +37 -9
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/instructions/domain.instructions.md +1 -1
- rpr_cli-0.1.30/src/rpr/scaffolds/special_files/camel_case_model.md +60 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/templates/registry.py +6 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/02-rpr-generate-domain.md +2 -2
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/08-rpr-add-template.md +1 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_add.py +75 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_context.py +42 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_generate_domain.py +37 -0
- rpr_cli-0.1.28/src/rpr/__init__.py +0 -1
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/.github/agents/story.agent.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/.github/workflows/publish-pypi.yml +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/.gitignore +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/CLAUDE.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/GEMINI.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/LICENSE +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/instructions/all.instructions.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/instructions/api.instructions.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/instructions/domain.instructions.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/instructions/frontend.instructions.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/instructions/rust-engine.instructions.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/instructions/setup-guide.instructions.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/instructions/tooling-setup.instructions.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/instructions/tooling.instructions.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/scaffolds/README.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/scaffolds/api/main.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/scaffolds/domain/base-repo.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/scaffolds/domain/base_entity.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/scaffolds/frontend/api.service.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/scaffolds/frontend/useStateNavigation.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/scaffolds/frontend/virtual-list/VirtualComponent.spec.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/scaffolds/frontend/virtual-list/VirtualComponent.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/scaffolds/frontend/virtual-list/VirtualComponentList.spec.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/scaffolds/frontend/virtual-list/VirtualComponentList.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/scaffolds/frontend/virtual-list/index.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/changelogs/mui_v9.txt +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/code-map.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/nx_uv_setup.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/patch_output.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/plan-languageAwareTemplateAdd.prompt.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/pyproject.toml +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/Cargo.lock +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/Cargo.toml +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/pyproject.toml +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/rpr_parser.pyi +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/src/config/container.rs +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/src/config/mod.rs +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/src/config/settings.rs +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/src/graph.rs +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/src/lib.rs +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/src/models/dtos/mod.rs +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/src/models/entities/mod.rs +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/src/models/entities/users.rs +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/src/models/mod.rs +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/src/parse.rs +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/src/repos/base.rs +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/src/repos/mod.rs +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/src/repos/users.rs +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/src/resolve.rs +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/src/walker.rs +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/rpr-parser/uv.lock +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/special_files.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/agent/__init__.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/agent/approval.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/agent/bootstrap.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/agent/client.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/agent/control.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/agent/mock.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/agent/runtime.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/agent/session.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/agent/tools/__init__.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/agent/tools/base.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/agent/tools/mutating.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/agent/tools/readonly.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/agent/tools/registry.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/application/__init__.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/application/catalog.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/application/chat_service.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/application/checks.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/application/cli_adapter.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/application/completer.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/application/conversation_service.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/application/prompt_service.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/application/selector.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/application/shell.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/checks/__init__.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/checks/base.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/checks/instructions.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/checks/packages.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/checks/workspace.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/cli.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/commands/__init__.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/commands/add.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/commands/chat.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/commands/check.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/commands/generate/__init__.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/commands/generate/api.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/commands/generate/engine.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/commands/generate/storybook.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/commands/generate/ui.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/commands/init.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/commands/map.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/commands/refresh.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/commands/settings.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/commands/sync.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/dependencies.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/dependency_manifest_data.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/generators/__init__.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/generators/base.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/generators/claude.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/generators/copilot.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/generators/cursor.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/generators/gemini.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/generators/github.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/manifest_refresh.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/map/__init__.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/map/architecture.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/map/chains.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/map/classifier.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/map/coverage.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/map/dependencies.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/map/extractor.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/map/graph.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/map/output.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/map/responsibility.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/map/topology.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/map/walker.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/domain/base_entity.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/domain/base_repo.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/domain/container.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/domain/settings.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/instructions/all.instructions.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/instructions/api.instructions.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/instructions/frontend.instructions.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/instructions/rust-engine.instructions.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/instructions/setup-guide.instructions.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/instructions/tooling-setup.instructions.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/instructions/tooling.instructions.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/README.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/client/index.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/client/types.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/ChatComposer.spec.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/ChatComposer.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/__screenshots__/ChatComposer.spec.tsx/ChatComposer-renders-custom-action-buttons-beside-the-attachment-control-1.png +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/fileDrop.spec.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/fileDrop.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/index.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/ChatComposerMentionTokens.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/ChatSuggestionsPopover.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/LocalFileSuggestionAction.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/index.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/localFileSuggestions.spec.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/localFileSuggestions.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/triggerDetection.spec.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/triggerDetection.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/types.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/suggestions/useChatSuggestions.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/types.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/useChatComposer.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/useChatStream.spec.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/composer/useChatStream.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/index.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/testing/createMockChatStreamClient.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/testing/createMockSuggestionProvider.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/testing/index.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/thread/ChatMessage.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/thread/ChatMessageContent.spec.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/thread/ChatMessageContent.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/thread/ChatThread.spec.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/thread/ChatThread.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/thread/README.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/thread/contentFormat.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/thread/index.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/thread/streaming.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/thread/types.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/virtual-list/VirtualComponent.spec.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/virtual-list/VirtualComponent.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/virtual-list/VirtualComponentList.spec.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/virtual-list/VirtualComponentList.tsx +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/chat/virtual-list/index.ts +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/fetch.service.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/sticky-navigation.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/sticky-navigation.spec.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/js_special_files/vitest-browser-config.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/special_files/domain_container.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/special_files/domain_settings.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/special_files/dto_util.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/special_files/encrypted_column.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/special_files/mapper_util.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/scaffolds/special_files/partial_update.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/templates/__init__.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/ui/__init__.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/ui/console.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/ui/markdown.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/ui/prompt_session.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/ui/renderers.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/ui/theme.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/src/rpr/workspace.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/README.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/00-bootstrap-cli.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/01-rpr-init.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/03-rpr-generate-api.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/04-rpr-generate-ui.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/05-rpr-generate-engine.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/06-rpr-generate-storybook.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/07-rpr-sync-rules.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/09-rpr-check.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/10-rpr-domain-config.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/chat/18-rpr-terminal-ui-foundation.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/chat/19-rpr-markdown-rendering.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/chat/20-rpr-chat-repl.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/chat/21-rpr-agent-tool-loop.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/chat/22-rpr-chat-tui.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/chat/23-rpr-chat-unified-command-shell.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/chat/24-rpr-async-chat-runtime-and-services.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/chat/25-rpr-prompt-service-and-conversation-lifecycle.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/chat/26-rpr-shared-command-catalog.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/chat/27-rpr-slash-command-selection-panel.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/chat/28-rpr-chat-cancellable-and-multiline-input.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/chat/29-rpr-file-context-selection.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/map/11-rpr-map-command.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/map/12-rpr-map-file-walker.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/map/13-rpr-map-rust-engine.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/map/13a-rpr-map-gitignore.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/map/14-rpr-map-graph-builder.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/map/15-rpr-map-analysis-bridge.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/map/16-rpr-map-layer-classifier.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/map/17-rpr-map-output.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/map/17a-rpr-map-directory-topology.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/map/17b-rpr-map-architecture-assessment.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/map/17c-rpr-map-representative-chains.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/completed/map/17d-rpr-map-multi-resolution-output.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/map/30-rpr-map-directory-view-and-cycle-detection.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/map/31-rpr-map-coupling-hotspots-and-verdict-reasoning.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/stories/map/32-rpr-map-dependencies-responsibilities-and-test-coverage.md +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/__init__.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_architecture.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_architecture_unwrapped.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_catalog.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_chat.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_chat_service.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_check.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_completer.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_generate_api.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_generate_engine.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_generate_storybook.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_generate_ui.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_init.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_map.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_map_chains.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_map_classifier.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_map_coverage.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_map_dependencies.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_map_extractor.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_map_graph.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_map_output.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_map_responsibility.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_map_topology.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_map_walker.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_packaging.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_prompt_session.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_refresh.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_rpr_parser_stub.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_selector.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_settings.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_sync.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/tests/test_ui.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/update_output.py +0 -0
- {rpr_cli-0.1.28 → rpr_cli-0.1.30}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rpr-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.30
|
|
4
4
|
Summary: RPR CLI -- React Python Rust monorepo scaffolding orchestrator
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -109,6 +109,7 @@ Sync project context to your favorite AI tools and add common code patterns.
|
|
|
109
109
|
```bash
|
|
110
110
|
rpr sync rules # Sync AI instructions to Cursor, Copilot, Claude Code, and Gemini
|
|
111
111
|
rpr add template python mapper_util # Add a Python code template to your project
|
|
112
|
+
rpr add template python camel_case_model
|
|
112
113
|
rpr add template node sticky_navigation --include-tests
|
|
113
114
|
rpr add template node -l # List available Node/TSX templates
|
|
114
115
|
rpr add template --list # List all available code templates
|
|
@@ -94,6 +94,7 @@ Sync project context to your favorite AI tools and add common code patterns.
|
|
|
94
94
|
```bash
|
|
95
95
|
rpr sync rules # Sync AI instructions to Cursor, Copilot, Claude Code, and Gemini
|
|
96
96
|
rpr add template python mapper_util # Add a Python code template to your project
|
|
97
|
+
rpr add template python camel_case_model
|
|
97
98
|
rpr add template node sticky_navigation --include-tests
|
|
98
99
|
rpr add template node -l # List available Node/TSX templates
|
|
99
100
|
rpr add template --list # List all available code templates
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.30"
|
|
@@ -17,7 +17,12 @@ console = Console()
|
|
|
17
17
|
|
|
18
18
|
_SCAFFOLD_DIR = Path(__file__).parent.parent.parent / "scaffolds" / "domain"
|
|
19
19
|
|
|
20
|
-
_UTILITY_TEMPLATES = [
|
|
20
|
+
_UTILITY_TEMPLATES = [
|
|
21
|
+
"mapper_util",
|
|
22
|
+
"dto_util",
|
|
23
|
+
"camel_case_model",
|
|
24
|
+
"partial_update",
|
|
25
|
+
]
|
|
21
26
|
|
|
22
27
|
|
|
23
28
|
@generate_app.command()
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
+
import shutil
|
|
4
5
|
import subprocess
|
|
5
6
|
from dataclasses import dataclass, field
|
|
6
7
|
from pathlib import Path
|
|
@@ -53,7 +54,7 @@ def _uv_activation_env(
|
|
|
53
54
|
) -> dict[str, str]:
|
|
54
55
|
effective_env = dict(env or {})
|
|
55
56
|
venv_dir = project_dir / ".venv"
|
|
56
|
-
venv_bin = venv_dir / "bin"
|
|
57
|
+
venv_bin = venv_dir / ("Scripts" if os.name == "nt" else "bin")
|
|
57
58
|
if venv_bin.exists():
|
|
58
59
|
current_path = effective_env.get("PATH", os.environ.get("PATH", ""))
|
|
59
60
|
effective_env["VIRTUAL_ENV"] = str(venv_dir)
|
|
@@ -61,6 +62,38 @@ def _uv_activation_env(
|
|
|
61
62
|
return effective_env
|
|
62
63
|
|
|
63
64
|
|
|
65
|
+
def _resolve_windows_command_shim(
|
|
66
|
+
cmd: list[str], env: dict[str, str] | None = None
|
|
67
|
+
) -> list[str]:
|
|
68
|
+
if os.name != "nt" or not cmd:
|
|
69
|
+
return cmd
|
|
70
|
+
|
|
71
|
+
executable = cmd[0]
|
|
72
|
+
if Path(executable).suffix or any(
|
|
73
|
+
separator and separator in executable for separator in (os.sep, os.altsep)
|
|
74
|
+
):
|
|
75
|
+
return cmd
|
|
76
|
+
|
|
77
|
+
resolved = shutil.which(executable, path=(env or os.environ).get("PATH"))
|
|
78
|
+
if resolved is None:
|
|
79
|
+
return cmd
|
|
80
|
+
|
|
81
|
+
return [resolved, *cmd[1:]]
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _format_display_command(cmd: list[str], env: dict[str, str] | None = None) -> str:
|
|
85
|
+
display_cmd = " ".join(cmd)
|
|
86
|
+
if not env:
|
|
87
|
+
return display_cmd
|
|
88
|
+
|
|
89
|
+
if os.name == "nt":
|
|
90
|
+
env_prefix = "; ".join(f'$env:{key}="{value}"' for key, value in env.items())
|
|
91
|
+
return f"{env_prefix}; {display_cmd}"
|
|
92
|
+
|
|
93
|
+
env_prefix = " ".join(f"{key}={value}" for key, value in env.items())
|
|
94
|
+
return f"{env_prefix} {display_cmd}"
|
|
95
|
+
|
|
96
|
+
|
|
64
97
|
@dataclass
|
|
65
98
|
class RunContext:
|
|
66
99
|
dry_run: bool = False
|
|
@@ -95,11 +128,7 @@ class RunContext:
|
|
|
95
128
|
supports_dry_run: bool = False,
|
|
96
129
|
) -> subprocess.CompletedProcess[str]:
|
|
97
130
|
resolved_cwd = str(cwd) if cwd else str(self.project_dir)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
display_cmd = " ".join(cmd)
|
|
101
|
-
if env_prefix:
|
|
102
|
-
display_cmd = f"{env_prefix} {display_cmd}"
|
|
131
|
+
display_cmd = _format_display_command(cmd, env)
|
|
103
132
|
|
|
104
133
|
if self.dry_run and not supports_dry_run:
|
|
105
134
|
render_command_start(display_cmd, resolved_cwd, is_dry_run=True)
|
|
@@ -109,9 +138,7 @@ class RunContext:
|
|
|
109
138
|
cmd + ["--dry-run"] if (self.dry_run and supports_dry_run) else cmd
|
|
110
139
|
)
|
|
111
140
|
if self.dry_run and supports_dry_run:
|
|
112
|
-
display_cmd =
|
|
113
|
-
if env_prefix:
|
|
114
|
-
display_cmd = f"{env_prefix} {display_cmd}"
|
|
141
|
+
display_cmd = _format_display_command(effective_cmd, env)
|
|
115
142
|
|
|
116
143
|
render_command_start(display_cmd, resolved_cwd, is_dry_run=False)
|
|
117
144
|
|
|
@@ -119,6 +146,7 @@ class RunContext:
|
|
|
119
146
|
if env:
|
|
120
147
|
effective_env = os.environ.copy()
|
|
121
148
|
effective_env.update(env)
|
|
149
|
+
effective_cmd = _resolve_windows_command_shim(effective_cmd, effective_env)
|
|
122
150
|
result = subprocess.run(
|
|
123
151
|
effective_cmd,
|
|
124
152
|
cwd=resolved_cwd,
|
|
@@ -78,7 +78,7 @@ npx nx run {name_underscore}_domain:migrate -- downgrade -1
|
|
|
78
78
|
- Reuse existing DTOs when the contract is the same. Do not create near-duplicate DTOs for every small variation.
|
|
79
79
|
- DTOs exposed through the API should stay minimal and focused on the contract, not internal persistence details.
|
|
80
80
|
- Mapper functions should live in the DTO or mapper layer and follow a clear `to_dto()` naming convention.
|
|
81
|
-
- DTOs that are serialized to JSON should
|
|
81
|
+
- DTOs that are serialized to JSON should inherit from `CamelCaseModel` in `utils/camel_case_model.py`.
|
|
82
82
|
- DTOs that represent external-service payloads can use `TypedDict` when a Pydantic model would add unnecessary weight.
|
|
83
83
|
- Internal data containers that are not serialized can use `@dataclass` when that is the simplest fit.
|
|
84
84
|
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
## Camel Case Model Template
|
|
2
|
+
|
|
3
|
+
Target path: `/packages/python/{name_underscore}_domain/src/{name_underscore}_domain/utils/camel_case_model.py`
|
|
4
|
+
|
|
5
|
+
Use this base model for DTOs that should accept snake_case, camelCase, and PascalCase input while serializing JSON with camelCase field names.
|
|
6
|
+
|
|
7
|
+
The first Python block is the generated file used by `rpr add template camel_case_model`.
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
from pydantic import AliasChoices, AliasGenerator, BaseModel, ConfigDict
|
|
11
|
+
from pydantic.alias_generators import to_camel, to_pascal
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def validation_alias_generator(field_name: str) -> AliasChoices:
|
|
15
|
+
"""
|
|
16
|
+
Generate validation aliases for camelCase, PascalCase, and snake_case field names.
|
|
17
|
+
|
|
18
|
+
Examples:
|
|
19
|
+
rules_checked -> accepts: rulesChecked, RulesChecked, rules_checked
|
|
20
|
+
user_id -> accepts: userId, UserId, user_id
|
|
21
|
+
"""
|
|
22
|
+
return AliasChoices(to_camel(field_name), to_pascal(field_name), field_name)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class CamelCaseModel(BaseModel):
|
|
26
|
+
"""
|
|
27
|
+
Base model that accepts flexible input field names and serializes JSON as camelCase.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
model_config = ConfigDict(
|
|
31
|
+
alias_generator=AliasGenerator(
|
|
32
|
+
validation_alias=validation_alias_generator,
|
|
33
|
+
serialization_alias=to_camel,
|
|
34
|
+
),
|
|
35
|
+
populate_by_name=True,
|
|
36
|
+
ser_json_timedelta="float",
|
|
37
|
+
validate_assignment=True,
|
|
38
|
+
)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from your_app_domain.utils.camel_case_model import CamelCaseModel
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class RuleCheckDTO(CamelCaseModel):
|
|
48
|
+
rules_checked: int
|
|
49
|
+
user_id: str
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
dto = RuleCheckDTO(rulesChecked=3, UserId="user-1")
|
|
53
|
+
payload = dto.model_dump(by_alias=True)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## What This Template Solves
|
|
57
|
+
|
|
58
|
+
- API DTOs can accept payloads from clients that use snake_case, camelCase, or PascalCase.
|
|
59
|
+
- JSON serialization remains consistent by using camelCase aliases.
|
|
60
|
+
- Assignment validation stays enabled for DTO instances that are updated in code.
|
|
@@ -211,6 +211,12 @@ TEMPLATES: dict[str, TemplateEntry] = {
|
|
|
211
211
|
source_filename="dto_util.md",
|
|
212
212
|
target_path="packages/python/{name_underscore}_domain/src/{name_underscore}_domain/utils/dto_util.py",
|
|
213
213
|
),
|
|
214
|
+
"camel_case_model": python_template(
|
|
215
|
+
id="camel_case_model",
|
|
216
|
+
description="Pydantic BaseModel with camelCase JSON and flexible validation aliases",
|
|
217
|
+
source_filename="camel_case_model.md",
|
|
218
|
+
target_path="packages/python/{name_underscore}_domain/src/{name_underscore}_domain/utils/camel_case_model.py",
|
|
219
|
+
),
|
|
214
220
|
"partial_update": python_template(
|
|
215
221
|
id="partial_update",
|
|
216
222
|
description="apply_partial_update utility for PATCH endpoints",
|
|
@@ -74,8 +74,8 @@ The `project.json` must define at minimum `test` and `lint` targets. Use `uv run
|
|
|
74
74
|
|
|
75
75
|
- The domain package name uses underscores in the Python import path (`{name_underscore}_domain`) and dashes in the directory and `pyproject.toml` name (`{name}-domain`).
|
|
76
76
|
- Use `uv add` if stored dependencies need to be managed programmatically.
|
|
77
|
-
- The utils folder is scaffolded empty; use `rpr add template mapper_util`, `rpr add template dto_util`, `rpr add template partial_update`, or `rpr add template encrypted_column` to add those utilities.
|
|
78
|
-
- After scaffolding, offer to run `rpr add template` for the most common utilities (mapper_util, dto_util, partial_update).
|
|
77
|
+
- The utils folder is scaffolded empty; use `rpr add template mapper_util`, `rpr add template dto_util`, `rpr add template camel_case_model`, `rpr add template partial_update`, or `rpr add template encrypted_column` to add those utilities.
|
|
78
|
+
- After scaffolding, offer to run `rpr add template` for the most common utilities (mapper_util, dto_util, camel_case_model, partial_update).
|
|
79
79
|
- `config/settings.py` and `config/container.py` are generated from `src/rpr/scaffolds/domain/settings.md` and `container.md` (bundled templates that mirror `special_files/domain_settings.md` and `special_files/domain_container.md`). They can be reset at any time via `rpr add template domain_settings` or `rpr add template domain_container`.
|
|
80
80
|
- If the domain Container ever needs lifecycle hooks (startup/shutdown), see the lifecycle extension pattern documented in Story 10.
|
|
81
81
|
|
|
@@ -25,6 +25,7 @@ Neither `rpr init` nor `rpr generate ui` add these files directly — they deleg
|
|
|
25
25
|
| `domain_container` | `special_files/domain_container.md` | `packages/python/domain/src/<name>_domain/config/container.py` |
|
|
26
26
|
| `mapper_util` | `special_files/mapper_util.md` | Python domain package (e.g., `packages/python/domain/src/<name>_domain/utils/mapper_util.py`) |
|
|
27
27
|
| `dto_util` | `special_files/dto_util.md` | Python domain package utils |
|
|
28
|
+
| `camel_case_model` | `special_files/camel_case_model.md` | Python domain package utils |
|
|
28
29
|
| `partial_update` | `special_files/partial_update.md` | Python domain package utils |
|
|
29
30
|
| `encrypted_column` | `special_files/encrypted_column.md` | Python domain package (models/config) |
|
|
30
31
|
| `sticky_navigation` | `js_special_files/sticky-navigation.md` | `packages/node/<name>-ui/src/hooks/useStateNavigation.ts` |
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import importlib.util
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
|
|
6
|
+
import pytest
|
|
5
7
|
from typer.testing import CliRunner
|
|
6
8
|
|
|
7
9
|
from rpr.cli import app
|
|
@@ -39,6 +41,7 @@ def test_add_template_list():
|
|
|
39
41
|
assert "domain_settings" in result.stdout
|
|
40
42
|
assert "domain_container" in result.stdout
|
|
41
43
|
assert "mapper_util" in result.stdout
|
|
44
|
+
assert "camel_case_model" in result.stdout
|
|
42
45
|
assert "sticky_navigation" in result.stdout
|
|
43
46
|
assert "virtual_list" in result.stdout
|
|
44
47
|
# Should show placeholders if no name/config
|
|
@@ -61,10 +64,12 @@ def test_add_template_list_by_language():
|
|
|
61
64
|
assert "node fetch_service" in node_result.stdout
|
|
62
65
|
assert "node virtual_list" in node_result.stdout
|
|
63
66
|
assert "python mapper_util" not in node_result.stdout
|
|
67
|
+
assert "python camel_case_model" not in node_result.stdout
|
|
64
68
|
|
|
65
69
|
python_result = runner.invoke(app, ["add", "template", "python", "--list"])
|
|
66
70
|
assert python_result.exit_code == 0, python_result.stdout
|
|
67
71
|
assert "python mapper_util" in python_result.stdout
|
|
72
|
+
assert "python camel_case_model" in python_result.stdout
|
|
68
73
|
assert "python domain_settings" in python_result.stdout
|
|
69
74
|
assert "node sticky_navigation" not in python_result.stdout
|
|
70
75
|
|
|
@@ -146,6 +151,76 @@ def test_add_domain_container_template_execution():
|
|
|
146
151
|
assert "override __new__" in content
|
|
147
152
|
|
|
148
153
|
|
|
154
|
+
def test_add_camel_case_model_template_execution():
|
|
155
|
+
with runner.isolated_filesystem():
|
|
156
|
+
project_dir = Path.cwd()
|
|
157
|
+
scaffolds_dir = _repo_scaffolds_dir()
|
|
158
|
+
_write_rpr_config(scaffolds_dir)
|
|
159
|
+
|
|
160
|
+
result = runner.invoke(app, ["add", "template", "camel_case_model", "--force"])
|
|
161
|
+
assert result.exit_code == 0, result.stdout
|
|
162
|
+
|
|
163
|
+
target_path = (
|
|
164
|
+
project_dir
|
|
165
|
+
/ "packages/python/test_app_domain/src/test_app_domain/utils/camel_case_model.py"
|
|
166
|
+
)
|
|
167
|
+
assert target_path.exists()
|
|
168
|
+
|
|
169
|
+
content = target_path.read_text()
|
|
170
|
+
assert "class CamelCaseModel(BaseModel):" in content
|
|
171
|
+
assert (
|
|
172
|
+
"def validation_alias_generator(field_name: str) -> AliasChoices:"
|
|
173
|
+
in content
|
|
174
|
+
)
|
|
175
|
+
assert (
|
|
176
|
+
"AliasChoices(to_camel(field_name), to_pascal(field_name), field_name)"
|
|
177
|
+
in content
|
|
178
|
+
)
|
|
179
|
+
assert "serialization_alias=to_camel" in content
|
|
180
|
+
assert "populate_by_name=True" in content
|
|
181
|
+
assert "validate_assignment=True" in content
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def test_camel_case_model_accepts_common_alias_styles():
|
|
185
|
+
pytest.importorskip("pydantic")
|
|
186
|
+
|
|
187
|
+
with runner.isolated_filesystem():
|
|
188
|
+
project_dir = Path.cwd()
|
|
189
|
+
scaffolds_dir = _repo_scaffolds_dir()
|
|
190
|
+
_write_rpr_config(scaffolds_dir)
|
|
191
|
+
|
|
192
|
+
result = runner.invoke(app, ["add", "template", "camel_case_model", "--force"])
|
|
193
|
+
assert result.exit_code == 0, result.stdout
|
|
194
|
+
|
|
195
|
+
target_path = (
|
|
196
|
+
project_dir
|
|
197
|
+
/ "packages/python/test_app_domain/src/test_app_domain/utils/camel_case_model.py"
|
|
198
|
+
)
|
|
199
|
+
module_spec = importlib.util.spec_from_file_location(
|
|
200
|
+
"camel_case_model", target_path
|
|
201
|
+
)
|
|
202
|
+
assert module_spec is not None
|
|
203
|
+
assert module_spec.loader is not None
|
|
204
|
+
module = importlib.util.module_from_spec(module_spec)
|
|
205
|
+
module_spec.loader.exec_module(module)
|
|
206
|
+
|
|
207
|
+
class RuleCheckDTO(module.CamelCaseModel):
|
|
208
|
+
rules_checked: int
|
|
209
|
+
user_id: str
|
|
210
|
+
|
|
211
|
+
camel_dto = RuleCheckDTO(rulesChecked=2, userId="user-1")
|
|
212
|
+
pascal_dto = RuleCheckDTO(RulesChecked=3, UserId="user-2")
|
|
213
|
+
snake_dto = RuleCheckDTO(rules_checked=4, user_id="user-3")
|
|
214
|
+
|
|
215
|
+
assert camel_dto.rules_checked == 2
|
|
216
|
+
assert pascal_dto.user_id == "user-2"
|
|
217
|
+
assert snake_dto.rules_checked == 4
|
|
218
|
+
assert snake_dto.model_dump(by_alias=True) == {
|
|
219
|
+
"rulesChecked": 4,
|
|
220
|
+
"userId": "user-3",
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
|
|
149
224
|
def test_add_template_dry_run():
|
|
150
225
|
with runner.isolated_filesystem():
|
|
151
226
|
scaffolds_dir = _repo_scaffolds_dir()
|
|
@@ -75,6 +75,37 @@ class TestRunCommandLive:
|
|
|
75
75
|
_, kwargs = mock_run.call_args
|
|
76
76
|
assert kwargs["env"]["NX_NO_CLOUD"] == "true"
|
|
77
77
|
|
|
78
|
+
def test_run_uv_command_uses_windows_venv_scripts_path(self, tmp_path):
|
|
79
|
+
scripts_dir = tmp_path / ".venv" / "Scripts"
|
|
80
|
+
scripts_dir.mkdir(parents=True)
|
|
81
|
+
ctx = make_ctx(dry_run=False, project_dir=tmp_path)
|
|
82
|
+
fake_result = completed(["uv", "sync"])
|
|
83
|
+
|
|
84
|
+
with (
|
|
85
|
+
patch("rpr.context.os.name", "nt"),
|
|
86
|
+
patch("rpr.context.shutil.which", return_value=None),
|
|
87
|
+
patch("subprocess.run", return_value=fake_result) as mock_run,
|
|
88
|
+
):
|
|
89
|
+
ctx.run_uv_command(["uv", "sync"])
|
|
90
|
+
|
|
91
|
+
_, kwargs = mock_run.call_args
|
|
92
|
+
assert kwargs["env"]["VIRTUAL_ENV"] == str(tmp_path / ".venv")
|
|
93
|
+
assert kwargs["env"]["PATH"].startswith(str(scripts_dir))
|
|
94
|
+
|
|
95
|
+
def test_resolves_windows_command_shim_before_executing(self):
|
|
96
|
+
ctx = make_ctx(dry_run=False)
|
|
97
|
+
fake_result = completed(["npx", "nx", "init"])
|
|
98
|
+
with (
|
|
99
|
+
patch("rpr.context.os.name", "nt"),
|
|
100
|
+
patch("rpr.context.shutil.which", return_value=r"C:\\nodejs\\npx.cmd") as mock_which,
|
|
101
|
+
patch("subprocess.run", return_value=fake_result) as mock_run,
|
|
102
|
+
):
|
|
103
|
+
ctx.run_command(["npx", "nx", "init"], env={"NX_NO_CLOUD": "true"})
|
|
104
|
+
|
|
105
|
+
args, _ = mock_run.call_args
|
|
106
|
+
assert args[0] == [r"C:\\nodejs\\npx.cmd", "nx", "init"]
|
|
107
|
+
mock_which.assert_called_once()
|
|
108
|
+
|
|
78
109
|
|
|
79
110
|
# ---------------------------------------------------------------------------
|
|
80
111
|
# run_command — dry-run mode, nested CLI does NOT support --dry-run
|
|
@@ -119,6 +150,17 @@ class TestRunCommandDryRunUnsupported:
|
|
|
119
150
|
captured = capsys.readouterr().out
|
|
120
151
|
assert "NX_NO_CLOUD=true npx nx init" in captured
|
|
121
152
|
|
|
153
|
+
def test_dry_run_shows_powershell_env_prefix_on_windows(self, capsys):
|
|
154
|
+
ctx = make_ctx(dry_run=True)
|
|
155
|
+
with (
|
|
156
|
+
patch("rpr.context.os.name", "nt"),
|
|
157
|
+
patch("rpr.ui.renderers.console", Console(highlight=False, no_color=True)),
|
|
158
|
+
patch("subprocess.run"),
|
|
159
|
+
):
|
|
160
|
+
ctx.run_command(["npx", "nx", "init"], env={"NX_NO_CLOUD": "true"})
|
|
161
|
+
captured = capsys.readouterr().out
|
|
162
|
+
assert '$env:NX_NO_CLOUD="true"; npx nx init' in captured
|
|
163
|
+
|
|
122
164
|
|
|
123
165
|
# ---------------------------------------------------------------------------
|
|
124
166
|
# run_command — dry-run mode, nested CLI DOES support --dry-run
|
|
@@ -184,6 +184,43 @@ def test_generate_domain_with_migrations_scaffolds_alembic_and_target(monkeypatc
|
|
|
184
184
|
]
|
|
185
185
|
|
|
186
186
|
|
|
187
|
+
def test_generate_domain_can_run_common_utility_templates(monkeypatch):
|
|
188
|
+
recorded_calls: list[tuple[list[str], Path | str | None]] = []
|
|
189
|
+
|
|
190
|
+
def fake_run_command(
|
|
191
|
+
self, cmd, *, cwd=None, env=None, capture=False, supports_dry_run=False
|
|
192
|
+
):
|
|
193
|
+
recorded_calls.append((cmd, cwd))
|
|
194
|
+
return _completed(cmd)
|
|
195
|
+
|
|
196
|
+
monkeypatch.setattr("rpr.context.RunContext.run_command", fake_run_command)
|
|
197
|
+
monkeypatch.setattr(
|
|
198
|
+
"rpr.commands.generate.domain.typer.confirm", lambda *args, **kwargs: True
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
with runner.isolated_filesystem():
|
|
202
|
+
_write_root_pyproject()
|
|
203
|
+
|
|
204
|
+
result = runner.invoke(app, ["generate", "domain", "my-app"])
|
|
205
|
+
assert result.exit_code == 0, result.stdout
|
|
206
|
+
|
|
207
|
+
utility_commands = [cmd for cmd, _ in recorded_calls[2:]]
|
|
208
|
+
assert utility_commands == [
|
|
209
|
+
["rpr", "add", "template", "python", "mapper_util", "--name", "my-app"],
|
|
210
|
+
["rpr", "add", "template", "python", "dto_util", "--name", "my-app"],
|
|
211
|
+
[
|
|
212
|
+
"rpr",
|
|
213
|
+
"add",
|
|
214
|
+
"template",
|
|
215
|
+
"python",
|
|
216
|
+
"camel_case_model",
|
|
217
|
+
"--name",
|
|
218
|
+
"my-app",
|
|
219
|
+
],
|
|
220
|
+
["rpr", "add", "template", "python", "partial_update", "--name", "my-app"],
|
|
221
|
+
]
|
|
222
|
+
|
|
223
|
+
|
|
187
224
|
def test_generate_domain_dry_run_previews_config_files(monkeypatch, capsys):
|
|
188
225
|
monkeypatch.setattr(
|
|
189
226
|
"rpr.context.console", Console(highlight=False, no_color=True), raising=False
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.1.28"
|
|
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
|
{rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/instructions/rust-engine.instructions.md
RENAMED
|
File without changes
|
{rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/instructions/setup-guide.instructions.md
RENAMED
|
File without changes
|
{rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/instructions/tooling-setup.instructions.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/scaffolds/frontend/useStateNavigation.ts
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rpr_cli-0.1.28 → rpr_cli-0.1.30}/Sample-dot-github/scaffolds/frontend/virtual-list/index.ts
RENAMED
|
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
|
|
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
|
|
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
|