rpr-cli 0.1.20__tar.gz → 0.1.22__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.20 → rpr_cli-0.1.22}/PKG-INFO +1 -1
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/instructions/all.instructions.md +8 -8
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/instructions/frontend.instructions.md +1 -1
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/instructions/rust-engine.instructions.md +4 -4
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/instructions/setup-guide.instructions.md +8 -9
- {rpr_cli-0.1.20/src/rpr/scaffolds → rpr_cli-0.1.22/Sample-dot-github}/instructions/tooling-setup.instructions.md +1 -1
- rpr_cli-0.1.22/src/rpr/__init__.py +1 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/checks/instructions.py +19 -2
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/checks/packages.py +71 -77
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/generate/api.py +16 -21
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/generate/domain.py +28 -29
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/generate/engine.py +4 -4
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/generate/storybook.py +31 -18
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/generate/ui.py +37 -12
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/init.py +52 -42
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/sync.py +7 -3
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/context.py +30 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/dependencies.py +32 -8
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/dependency_manifest_data.py +0 -9
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/generators/base.py +4 -2
- rpr_cli-0.1.22/src/rpr/generators/github.py +35 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/domain/container.md +1 -1
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/domain/settings.md +1 -1
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/instructions/all.instructions.md +8 -8
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/instructions/domain.instructions.md +5 -5
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/instructions/frontend.instructions.md +1 -1
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/instructions/rust-engine.instructions.md +4 -4
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/instructions/setup-guide.instructions.md +19 -20
- {rpr_cli-0.1.20/Sample-dot-github → rpr_cli-0.1.22/src/rpr/scaffolds}/instructions/tooling-setup.instructions.md +1 -1
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/special_files/domain_container.md +1 -1
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/special_files/domain_settings.md +1 -1
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/special_files/dto_util.md +1 -1
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/special_files/encrypted_column.md +1 -1
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/special_files/mapper_util.md +1 -1
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/special_files/partial_update.md +1 -1
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/templates/registry.py +8 -8
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/workspace.py +6 -36
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_add.py +4 -3
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_check.py +42 -75
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_generate_api.py +14 -11
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_generate_domain.py +41 -22
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_generate_engine.py +17 -15
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_generate_storybook.py +49 -30
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_generate_ui.py +32 -60
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_init.py +58 -35
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_sync.py +17 -4
- rpr_cli-0.1.20/src/rpr/__init__.py +0 -1
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/.github/agents/story.agent.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/.github/workflows/publish-pypi.yml +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/.gitignore +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/CLAUDE.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/GEMINI.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/LICENSE +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/README.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/instructions/api.instructions.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/instructions/domain.instructions.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/instructions/tooling.instructions.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/scaffolds/README.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/scaffolds/api/main.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/scaffolds/domain/base-repo.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/scaffolds/domain/base_entity.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/scaffolds/frontend/api.service.ts +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/scaffolds/frontend/useStateNavigation.ts +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/changelogs/mui_v9.txt +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/code-map.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/nx_uv_setup.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/patch_output.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/pyproject.toml +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/Cargo.lock +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/Cargo.toml +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/pyproject.toml +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/rpr_parser.pyi +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/config/container.rs +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/config/mod.rs +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/config/settings.rs +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/graph.rs +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/lib.rs +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/models/dtos/mod.rs +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/models/entities/mod.rs +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/models/entities/users.rs +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/models/mod.rs +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/parse.rs +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/repos/base.rs +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/repos/mod.rs +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/repos/users.rs +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/resolve.rs +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/walker.rs +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/uv.lock +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/special_files.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/__init__.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/approval.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/bootstrap.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/client.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/control.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/mock.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/runtime.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/session.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/tools/__init__.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/tools/base.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/tools/mutating.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/tools/readonly.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/tools/registry.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/__init__.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/catalog.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/chat_service.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/checks.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/cli_adapter.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/completer.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/conversation_service.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/prompt_service.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/selector.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/shell.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/checks/__init__.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/checks/base.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/checks/workspace.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/cli.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/__init__.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/add.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/chat.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/check.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/generate/__init__.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/map.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/refresh.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/settings.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/generators/__init__.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/generators/claude.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/generators/copilot.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/generators/cursor.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/generators/gemini.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/manifest_refresh.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/__init__.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/architecture.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/chains.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/classifier.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/coverage.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/dependencies.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/extractor.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/graph.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/output.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/responsibility.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/topology.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/walker.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/domain/base_entity.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/domain/base_repo.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/instructions/api.instructions.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/instructions/tooling.instructions.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/js_special_files/fetch.service.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/js_special_files/sticky-navigation.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/templates/__init__.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/ui/__init__.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/ui/console.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/ui/markdown.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/ui/prompt_session.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/ui/renderers.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/ui/theme.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/README.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/00-bootstrap-cli.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/01-rpr-init.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/02-rpr-generate-domain.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/03-rpr-generate-api.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/04-rpr-generate-ui.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/05-rpr-generate-engine.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/06-rpr-generate-storybook.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/07-rpr-sync-rules.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/08-rpr-add-template.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/09-rpr-check.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/10-rpr-domain-config.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/18-rpr-terminal-ui-foundation.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/19-rpr-markdown-rendering.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/20-rpr-chat-repl.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/21-rpr-agent-tool-loop.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/22-rpr-chat-tui.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/23-rpr-chat-unified-command-shell.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/24-rpr-async-chat-runtime-and-services.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/25-rpr-prompt-service-and-conversation-lifecycle.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/26-rpr-shared-command-catalog.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/27-rpr-slash-command-selection-panel.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/28-rpr-chat-cancellable-and-multiline-input.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/29-rpr-file-context-selection.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/11-rpr-map-command.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/12-rpr-map-file-walker.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/13-rpr-map-rust-engine.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/13a-rpr-map-gitignore.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/14-rpr-map-graph-builder.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/15-rpr-map-analysis-bridge.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/16-rpr-map-layer-classifier.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/17-rpr-map-output.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/17a-rpr-map-directory-topology.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/17b-rpr-map-architecture-assessment.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/17c-rpr-map-representative-chains.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/17d-rpr-map-multi-resolution-output.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/map/30-rpr-map-directory-view-and-cycle-detection.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/map/31-rpr-map-coupling-hotspots-and-verdict-reasoning.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/map/32-rpr-map-dependencies-responsibilities-and-test-coverage.md +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/__init__.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_architecture.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_architecture_unwrapped.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_catalog.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_chat.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_chat_service.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_completer.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_context.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_chains.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_classifier.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_coverage.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_dependencies.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_extractor.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_graph.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_output.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_responsibility.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_topology.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_walker.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_packaging.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_prompt_session.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_refresh.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_rpr_parser_stub.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_selector.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_settings.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_ui.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/update_output.py +0 -0
- {rpr_cli-0.1.20 → rpr_cli-0.1.22}/uv.lock +0 -0
|
@@ -24,14 +24,14 @@ This project uses an NX + UV monorepo with a domain-driven design approach. Appl
|
|
|
24
24
|
|
|
25
25
|
## Layout
|
|
26
26
|
|
|
27
|
-
| Path
|
|
28
|
-
|
|
|
29
|
-
| `apps/{
|
|
30
|
-
| `apps/{
|
|
31
|
-
| `packages/node/{
|
|
32
|
-
| `packages/node/sb`
|
|
33
|
-
| `packages/python/domain`
|
|
34
|
-
| `packages/python/{
|
|
27
|
+
| Path | Purpose |
|
|
28
|
+
| ------------------------------------------ | ------------------------------------------------------------------------ |
|
|
29
|
+
| `apps/{name_kebab}-web` | Thin frontend application shell |
|
|
30
|
+
| `apps/{name_underscore}_api` | FastAPI application |
|
|
31
|
+
| `packages/node/{name_kebab}-ui` | Reusable UI package with components, hooks, services, and state |
|
|
32
|
+
| `packages/node/sb` | Storybook package |
|
|
33
|
+
| `packages/python/domain` | Python domain package containing the `src/{name_underscore}_domain` code |
|
|
34
|
+
| `packages/python/{name_underscore}_engine` | Rust engine package exposed to Python |
|
|
35
35
|
|
|
36
36
|
## Instructions, Templates, and Scaffolds
|
|
37
37
|
|
|
@@ -11,7 +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 `@{
|
|
14
|
+
- Import the generated shared UI package through the app-scoped package name `@{name_kebab}/ui`, such as `@testapp/ui`, not `@repo/{name_kebab}-ui`.
|
|
15
15
|
- Prefer a shared base API service at `src/services/base/api.service.ts` when the UI package needs centralized fetch behavior.
|
|
16
16
|
- Prefer a shared `useStateNavigation` hook at `src/hooks/useStateNavigation.ts` when UI state should persist in the URL.
|
|
17
17
|
- Reuse existing components, hooks, and service patterns before introducing a new abstraction.
|
{rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/instructions/rust-engine.instructions.md
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
applyTo: "packages/python
|
|
2
|
+
applyTo: "packages/python/*_engine/**"
|
|
3
3
|
description: "Rust + PyO3 engine build, lint, and Python bindings"
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -9,9 +9,9 @@ Use Rust for performance-sensitive code that needs a Python-facing API. This pac
|
|
|
9
9
|
|
|
10
10
|
## Structure
|
|
11
11
|
|
|
12
|
-
- Package root: `packages/python/{
|
|
13
|
-
- Rust source: `packages/python/{
|
|
14
|
-
- Python build metadata: `packages/python/{
|
|
12
|
+
- Package root: `packages/python/{name_underscore}_engine`
|
|
13
|
+
- Rust source: `packages/python/{name_underscore}_engine/src/lib.rs`
|
|
14
|
+
- Python build metadata: `packages/python/{name_underscore}_engine/pyproject.toml`
|
|
15
15
|
- Type stubs: keep a `.pyi` file next to the package root for editor support
|
|
16
16
|
|
|
17
17
|
## Build and Tooling
|
{rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/instructions/setup-guide.instructions.md
RENAMED
|
@@ -24,18 +24,17 @@ Use this guidance when validating or changing the monorepo setup against the RPR
|
|
|
24
24
|
## Naming And Layout
|
|
25
25
|
|
|
26
26
|
- Use kebab-case for project roots and Nx project names.
|
|
27
|
-
- Keep the frontend app at `apps/{
|
|
28
|
-
- Keep the FastAPI app at `apps/{
|
|
29
|
-
- Keep the reusable React library at `packages/node/{
|
|
27
|
+
- Keep the frontend app at `apps/{name_kebab}-web`.
|
|
28
|
+
- Keep the FastAPI app at `apps/{name_underscore}_api`.
|
|
29
|
+
- Keep the reusable React library at `packages/node/{name_kebab}-ui`.
|
|
30
30
|
- Keep the dedicated Storybook host at `packages/node/sb`.
|
|
31
31
|
- Keep the Python domain package at `packages/python/domain`.
|
|
32
32
|
- Keep the domain import package at `packages/python/domain/src/{name_underscore}_domain` so imports read as `from {name_underscore}_domain ...`.
|
|
33
|
-
- Keep optional Rust engine packages at `packages/python/{
|
|
33
|
+
- Keep optional Rust engine packages at `packages/python/{name_underscore}_engine` unless the product contract changes.
|
|
34
34
|
|
|
35
35
|
## Python Naming Rule
|
|
36
36
|
|
|
37
|
-
- Use
|
|
38
|
-
- Use snake_case for the import package inside `src/`, for example `apps/{name}-api/src/{name}_api`.
|
|
37
|
+
- Use snake_case for Python filesystem roots and import packages, for example `apps/{name_underscore}_api/src/{name_underscore}_api`.
|
|
39
38
|
- Apply the same rule to the domain package: keep the root directory `packages/python/domain`, but keep the import package at `src/{name_underscore}_domain`.
|
|
40
39
|
- Keep the Python package name in `pyproject.toml` kebab-case.
|
|
41
40
|
- Add a `tests/` directory for generated Python apps and libraries.
|
|
@@ -45,8 +44,8 @@ Use this guidance when validating or changing the monorepo setup against the RPR
|
|
|
45
44
|
- Generate React app and library projects in a way that preserves the expected Nx command surface.
|
|
46
45
|
- The web app should expose at least `serve`, `build`, `lint`, `test`, and `typecheck` when those capabilities exist in the generated project.
|
|
47
46
|
- The UI library should expose at least `build`, `lint`, `test`, and `typecheck`.
|
|
48
|
-
- Use app-scoped Node package names: `packages/node/{
|
|
49
|
-
- Import the shared UI package through `@{
|
|
47
|
+
- Use app-scoped Node package names: `packages/node/{name_kebab}-ui` publishes as `@{name_kebab}/ui`, `apps/{name_kebab}-web` publishes as `@{name_kebab}/web`, and Storybook publishes as `@{name_kebab}/sb`.
|
|
48
|
+
- Import the shared UI package through `@{name_kebab}/ui`, for example `import { AppThemeProvider } from "@testapp/ui"` for a `TestApp` workspace.
|
|
50
49
|
- 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.
|
|
51
50
|
- Keep Storybook as a dedicated host project at `packages/node/sb`; do not silently repurpose the UI library as the Storybook project.
|
|
52
51
|
|
|
@@ -84,7 +83,7 @@ npx nx run domain:migrate -- downgrade -1
|
|
|
84
83
|
- Project roots and import package names follow the kebab-case and snake_case rules.
|
|
85
84
|
- Python projects have both `src/` and `tests/`.
|
|
86
85
|
- The domain import package remains `src/{name_underscore}_domain`.
|
|
87
|
-
- Node imports use app-scoped package names such as `@{
|
|
86
|
+
- Node imports use app-scoped package names such as `@{name_kebab}/ui`, not stale `@repo/*` aliases.
|
|
88
87
|
- Storybook remains hosted in `packages/node/sb`.
|
|
89
88
|
- Workspace members and workspace dependency sources are complete.
|
|
90
89
|
- Generated instructions, checks, and scaffolds refer to the current contract rather than stale paths.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
applyTo: "pyproject.toml,nx.json,.pre-commit-config.yaml,package.json,apps/*/project.json,packages/**/project.json,apps/*/eslint.config.mjs,packages/**/eslint.config.mjs,packages/python
|
|
2
|
+
applyTo: "pyproject.toml,nx.json,.pre-commit-config.yaml,package.json,apps/*/project.json,packages/**/project.json,apps/*/eslint.config.mjs,packages/**/eslint.config.mjs,packages/python/*_engine/Cargo.toml"
|
|
3
3
|
description: "Use when setting up or modifying Ruff, TypeScript linting, ESLint, Prettier, cargo fmt, Clippy, or pre-commit in an RPR workspace"
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.22"
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
5
|
from rpr.checks.base import CheckResult
|
|
6
|
-
from rpr.generators.base import
|
|
6
|
+
from rpr.generators.base import interpolate
|
|
7
7
|
from rpr.templates.registry import TEMPLATES
|
|
8
8
|
|
|
9
9
|
|
|
@@ -25,6 +25,23 @@ def check_instructions(
|
|
|
25
25
|
)
|
|
26
26
|
)
|
|
27
27
|
|
|
28
|
+
# GitHub / VS Code workspace instructions
|
|
29
|
+
github_instructions = project_dir / ".github" / "instructions"
|
|
30
|
+
github_ok = github_instructions.exists() and any(
|
|
31
|
+
github_instructions.glob("*.instructions.md")
|
|
32
|
+
)
|
|
33
|
+
results.append(
|
|
34
|
+
CheckResult(
|
|
35
|
+
group="AI Instructions & Templates",
|
|
36
|
+
area="GitHub workspace instructions",
|
|
37
|
+
status=github_ok,
|
|
38
|
+
path=str(github_instructions)
|
|
39
|
+
if github_ok
|
|
40
|
+
else ".github/instructions/*.instructions.md missing",
|
|
41
|
+
suggestion="rpr sync rules --target github",
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
|
|
28
45
|
# Copilot instructions
|
|
29
46
|
copilot_file = project_dir / ".github" / "copilot-instructions.md"
|
|
30
47
|
results.append(
|
|
@@ -52,7 +69,7 @@ def check_instructions(
|
|
|
52
69
|
)
|
|
53
70
|
|
|
54
71
|
# Templates (only if domain package exists for Python, or UI library for JS)
|
|
55
|
-
has_domain = any(project_dir.glob("packages/python
|
|
72
|
+
has_domain = any(project_dir.glob("packages/python/*_domain"))
|
|
56
73
|
has_ui = any(project_dir.glob("packages/node/*-ui"))
|
|
57
74
|
|
|
58
75
|
template_ids = [
|
|
@@ -8,39 +8,41 @@ from rpr.checks.base import CheckResult
|
|
|
8
8
|
from rpr.dependencies import (
|
|
9
9
|
DOMAIN_RUNTIME_DEPENDENCIES,
|
|
10
10
|
MATURIN_SPEC,
|
|
11
|
-
ROOT_STORYBOOK_DEV_DEPENDENCIES,
|
|
12
|
-
STORYBOOK_DEV_DEPENDENCIES,
|
|
13
|
-
UI_LIBRARY_DEPENDENCIES,
|
|
14
|
-
UI_LIBRARY_DEV_DEPENDENCIES,
|
|
15
|
-
WEB_APP_DEV_DEPENDENCIES,
|
|
16
11
|
api_runtime_dependencies,
|
|
17
12
|
dependency_names,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
node_project_name,
|
|
14
|
+
npm_package_name,
|
|
15
|
+
python_project_name,
|
|
21
16
|
)
|
|
22
17
|
|
|
23
18
|
|
|
24
19
|
def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckResult]:
|
|
25
20
|
results: list[CheckResult] = []
|
|
26
21
|
name = variables.get("name", "<name>")
|
|
27
|
-
name_underscore = variables.get("name_underscore", name.replace("-", "_"))
|
|
22
|
+
name_underscore = variables.get("name_underscore", name.replace("-", "_")).lower()
|
|
23
|
+
domain_name = python_project_name(name, "domain")
|
|
24
|
+
api_name = python_project_name(name, "api")
|
|
25
|
+
ui_name = node_project_name(name, "ui")
|
|
26
|
+
web_name = node_project_name(name, "web")
|
|
28
27
|
|
|
29
28
|
pyproject = project_dir / "pyproject.toml"
|
|
30
29
|
workspace_members: set[str] = set()
|
|
31
30
|
if pyproject.exists():
|
|
32
31
|
try:
|
|
33
32
|
data = tomllib.loads(pyproject.read_text())
|
|
34
|
-
members =
|
|
35
|
-
"
|
|
33
|
+
members = (
|
|
34
|
+
data.get("tool", {})
|
|
35
|
+
.get("uv", {})
|
|
36
|
+
.get("workspace", {})
|
|
37
|
+
.get("members", [])
|
|
36
38
|
)
|
|
37
39
|
if isinstance(members, list):
|
|
38
40
|
workspace_members = set(members)
|
|
39
|
-
except
|
|
41
|
+
except OSError, tomllib.TOMLDecodeError:
|
|
40
42
|
workspace_members = set()
|
|
41
43
|
|
|
42
44
|
# Domain package
|
|
43
|
-
domain_dir = project_dir / "packages" / "python" /
|
|
45
|
+
domain_dir = project_dir / "packages" / "python" / domain_name
|
|
44
46
|
results.append(
|
|
45
47
|
CheckResult(
|
|
46
48
|
group="Generated Packages & Apps",
|
|
@@ -48,7 +50,7 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
|
|
|
48
50
|
status=domain_dir.exists(),
|
|
49
51
|
path=str(domain_dir)
|
|
50
52
|
if domain_dir.exists()
|
|
51
|
-
else "packages/python/
|
|
53
|
+
else f"packages/python/{domain_name}/ missing",
|
|
52
54
|
suggestion=f"rpr generate domain {name}",
|
|
53
55
|
)
|
|
54
56
|
)
|
|
@@ -57,7 +59,7 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
|
|
|
57
59
|
_check_python_layout(
|
|
58
60
|
area="Domain layout",
|
|
59
61
|
project_dir=domain_dir,
|
|
60
|
-
src_package=domain_dir / "src" /
|
|
62
|
+
src_package=domain_dir / "src" / domain_name,
|
|
61
63
|
suggestion=f"rpr generate domain {name}",
|
|
62
64
|
)
|
|
63
65
|
)
|
|
@@ -73,7 +75,7 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
|
|
|
73
75
|
_check_project_name(
|
|
74
76
|
area="Domain project name",
|
|
75
77
|
project_json=domain_dir / "project.json",
|
|
76
|
-
expected_name=
|
|
78
|
+
expected_name=domain_name,
|
|
77
79
|
suggestion=f"rpr generate domain {name}",
|
|
78
80
|
)
|
|
79
81
|
)
|
|
@@ -96,22 +98,22 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
|
|
|
96
98
|
CheckResult(
|
|
97
99
|
group="Generated Packages & Apps",
|
|
98
100
|
area="Domain workspace member",
|
|
99
|
-
status="packages/python/
|
|
100
|
-
path="packages/python/
|
|
101
|
-
if "packages/python/
|
|
102
|
-
else "packages/python/
|
|
101
|
+
status=f"packages/python/{domain_name}" in workspace_members,
|
|
102
|
+
path=f"packages/python/{domain_name}"
|
|
103
|
+
if f"packages/python/{domain_name}" in workspace_members
|
|
104
|
+
else f"packages/python/{domain_name} missing from [tool.uv.workspace].members",
|
|
103
105
|
suggestion=f"rpr generate domain {name}",
|
|
104
106
|
)
|
|
105
107
|
)
|
|
106
108
|
|
|
107
109
|
# API app
|
|
108
|
-
api_dir = project_dir / "apps" /
|
|
110
|
+
api_dir = project_dir / "apps" / api_name
|
|
109
111
|
results.append(
|
|
110
112
|
CheckResult(
|
|
111
113
|
group="Generated Packages & Apps",
|
|
112
114
|
area="API app",
|
|
113
115
|
status=api_dir.exists(),
|
|
114
|
-
path=str(api_dir) if api_dir.exists() else f"apps/{
|
|
116
|
+
path=str(api_dir) if api_dir.exists() else f"apps/{api_name}/ missing",
|
|
115
117
|
suggestion=f"rpr generate api {name}",
|
|
116
118
|
)
|
|
117
119
|
)
|
|
@@ -120,7 +122,7 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
|
|
|
120
122
|
_check_python_layout(
|
|
121
123
|
area="API layout",
|
|
122
124
|
project_dir=api_dir,
|
|
123
|
-
src_package=api_dir / "src" /
|
|
125
|
+
src_package=api_dir / "src" / api_name,
|
|
124
126
|
suggestion=f"rpr generate api {name}",
|
|
125
127
|
)
|
|
126
128
|
)
|
|
@@ -138,23 +140,23 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
|
|
|
138
140
|
pyproject=api_dir / "pyproject.toml",
|
|
139
141
|
required_dependencies=set(api_runtime_dependencies(name)),
|
|
140
142
|
suggestion=f"rpr generate api {name}",
|
|
141
|
-
required_sources={
|
|
143
|
+
required_sources={domain_name: {"workspace": True}},
|
|
142
144
|
)
|
|
143
145
|
)
|
|
144
146
|
results.append(
|
|
145
147
|
CheckResult(
|
|
146
148
|
group="Generated Packages & Apps",
|
|
147
149
|
area="API workspace member",
|
|
148
|
-
status=f"apps/{
|
|
149
|
-
path=f"apps/{
|
|
150
|
-
if f"apps/{
|
|
151
|
-
else f"apps/{
|
|
150
|
+
status=f"apps/{api_name}" in workspace_members,
|
|
151
|
+
path=f"apps/{api_name}"
|
|
152
|
+
if f"apps/{api_name}" in workspace_members
|
|
153
|
+
else f"apps/{api_name} missing from [tool.uv.workspace].members",
|
|
152
154
|
suggestion=f"rpr generate api {name}",
|
|
153
155
|
)
|
|
154
156
|
)
|
|
155
157
|
|
|
156
158
|
# UI library
|
|
157
|
-
ui_dir = project_dir / "packages" / "node" /
|
|
159
|
+
ui_dir = project_dir / "packages" / "node" / ui_name
|
|
158
160
|
results.append(
|
|
159
161
|
CheckResult(
|
|
160
162
|
group="Generated Packages & Apps",
|
|
@@ -179,22 +181,19 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
|
|
|
179
181
|
_check_node_dependency_contract(
|
|
180
182
|
area="UI install metadata",
|
|
181
183
|
package_json=ui_dir / "package.json",
|
|
182
|
-
|
|
183
|
-
required_dev_dependencies=mapping_dependency_names(
|
|
184
|
-
UI_LIBRARY_DEV_DEPENDENCIES
|
|
185
|
-
),
|
|
184
|
+
expected_name=f"@{npm_package_name(name)}/ui",
|
|
186
185
|
suggestion=f"rpr generate ui {name}",
|
|
187
186
|
)
|
|
188
187
|
)
|
|
189
188
|
|
|
190
189
|
# Web app
|
|
191
|
-
web_dir = project_dir / "apps" /
|
|
190
|
+
web_dir = project_dir / "apps" / web_name
|
|
192
191
|
results.append(
|
|
193
192
|
CheckResult(
|
|
194
193
|
group="Generated Packages & Apps",
|
|
195
194
|
area="Web app",
|
|
196
195
|
status=web_dir.exists(),
|
|
197
|
-
path=str(web_dir) if web_dir.exists() else f"apps/{
|
|
196
|
+
path=str(web_dir) if web_dir.exists() else f"apps/{web_name}/ missing",
|
|
198
197
|
suggestion=f"rpr generate ui {name} --no-library",
|
|
199
198
|
)
|
|
200
199
|
)
|
|
@@ -209,14 +208,9 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
|
|
|
209
208
|
)
|
|
210
209
|
results.append(
|
|
211
210
|
_check_node_dependency_contract(
|
|
212
|
-
area="Web
|
|
211
|
+
area="Web package metadata",
|
|
213
212
|
package_json=web_dir / "package.json",
|
|
214
|
-
|
|
215
|
-
web_app_dependencies(f"{name}-ui")
|
|
216
|
-
),
|
|
217
|
-
required_dev_dependencies=mapping_dependency_names(
|
|
218
|
-
WEB_APP_DEV_DEPENDENCIES
|
|
219
|
-
),
|
|
213
|
+
expected_name=f"@{npm_package_name(name)}/web",
|
|
220
214
|
suggestion=f"rpr generate ui {name} --no-library",
|
|
221
215
|
)
|
|
222
216
|
)
|
|
@@ -251,30 +245,15 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
|
|
|
251
245
|
)
|
|
252
246
|
results.append(
|
|
253
247
|
_check_node_dependency_contract(
|
|
254
|
-
area="Storybook host
|
|
248
|
+
area="Storybook host package metadata",
|
|
255
249
|
package_json=sb_dir / "package.json",
|
|
256
|
-
|
|
257
|
-
storybook_package_dependencies(f"{name}-ui")
|
|
258
|
-
),
|
|
259
|
-
required_dev_dependencies=mapping_dependency_names(
|
|
260
|
-
STORYBOOK_DEV_DEPENDENCIES
|
|
261
|
-
),
|
|
262
|
-
suggestion="rpr generate storybook",
|
|
263
|
-
)
|
|
264
|
-
)
|
|
265
|
-
results.append(
|
|
266
|
-
_check_node_dependency_contract(
|
|
267
|
-
area="Storybook root install metadata",
|
|
268
|
-
package_json=project_dir / "package.json",
|
|
269
|
-
required_dev_dependencies=mapping_dependency_names(
|
|
270
|
-
ROOT_STORYBOOK_DEV_DEPENDENCIES
|
|
271
|
-
),
|
|
250
|
+
expected_name=f"@{npm_package_name(name)}/sb",
|
|
272
251
|
suggestion="rpr generate storybook",
|
|
273
252
|
)
|
|
274
253
|
)
|
|
275
254
|
|
|
276
255
|
# Engine
|
|
277
|
-
engine_dir = next(project_dir.glob("packages/python
|
|
256
|
+
engine_dir = next(project_dir.glob("packages/python/*_engine"), None)
|
|
278
257
|
results.append(
|
|
279
258
|
CheckResult(
|
|
280
259
|
group="Generated Packages & Apps",
|
|
@@ -300,7 +279,7 @@ def _load_json(path: Path) -> dict[str, object] | None:
|
|
|
300
279
|
return None
|
|
301
280
|
try:
|
|
302
281
|
data = json.loads(path.read_text())
|
|
303
|
-
except
|
|
282
|
+
except OSError, json.JSONDecodeError:
|
|
304
283
|
return None
|
|
305
284
|
return data if isinstance(data, dict) else None
|
|
306
285
|
|
|
@@ -310,7 +289,7 @@ def _load_toml(path: Path) -> dict[str, object] | None:
|
|
|
310
289
|
return None
|
|
311
290
|
try:
|
|
312
291
|
data = tomllib.loads(path.read_text())
|
|
313
|
-
except
|
|
292
|
+
except OSError, tomllib.TOMLDecodeError:
|
|
314
293
|
return None
|
|
315
294
|
return data if isinstance(data, dict) else None
|
|
316
295
|
|
|
@@ -405,7 +384,9 @@ def _check_python_dependency_contract(
|
|
|
405
384
|
suggestion=suggestion,
|
|
406
385
|
)
|
|
407
386
|
|
|
408
|
-
project =
|
|
387
|
+
project = (
|
|
388
|
+
data.get("project", {}) if isinstance(data.get("project", {}), dict) else {}
|
|
389
|
+
)
|
|
409
390
|
dependencies = project.get("dependencies", []) if isinstance(project, dict) else []
|
|
410
391
|
dependency_set = set(dependencies) if isinstance(dependencies, list) else set()
|
|
411
392
|
missing_dependencies = sorted(required_dependencies.difference(dependency_set))
|
|
@@ -434,9 +415,7 @@ def _check_python_dependency_contract(
|
|
|
434
415
|
group="Generated Packages & Apps",
|
|
435
416
|
area=area,
|
|
436
417
|
status=status,
|
|
437
|
-
path=str(pyproject)
|
|
438
|
-
if status
|
|
439
|
-
else f"{pyproject} {'; '.join(details)}",
|
|
418
|
+
path=str(pyproject) if status else f"{pyproject} {'; '.join(details)}",
|
|
440
419
|
suggestion=suggestion,
|
|
441
420
|
)
|
|
442
421
|
|
|
@@ -446,6 +425,7 @@ def _check_node_dependency_contract(
|
|
|
446
425
|
area: str,
|
|
447
426
|
package_json: Path,
|
|
448
427
|
suggestion: str,
|
|
428
|
+
expected_name: str | None = None,
|
|
449
429
|
required_dependencies: set[str] | None = None,
|
|
450
430
|
required_dev_dependencies: set[str] | None = None,
|
|
451
431
|
) -> CheckResult:
|
|
@@ -459,6 +439,15 @@ def _check_node_dependency_contract(
|
|
|
459
439
|
suggestion=suggestion,
|
|
460
440
|
)
|
|
461
441
|
|
|
442
|
+
if expected_name is not None and data.get("name") != expected_name:
|
|
443
|
+
return CheckResult(
|
|
444
|
+
group="Generated Packages & Apps",
|
|
445
|
+
area=area,
|
|
446
|
+
status=False,
|
|
447
|
+
path=f"{package_json} expected name '{expected_name}'",
|
|
448
|
+
suggestion=suggestion,
|
|
449
|
+
)
|
|
450
|
+
|
|
462
451
|
dependencies = data.get("dependencies", {})
|
|
463
452
|
dev_dependencies = data.get("devDependencies", {})
|
|
464
453
|
dependency_keys = set(dependencies) if isinstance(dependencies, dict) else set()
|
|
@@ -486,9 +475,7 @@ def _check_node_dependency_contract(
|
|
|
486
475
|
group="Generated Packages & Apps",
|
|
487
476
|
area=area,
|
|
488
477
|
status=status,
|
|
489
|
-
path=str(package_json)
|
|
490
|
-
if status
|
|
491
|
-
else f"{package_json} {'; '.join(details)}",
|
|
478
|
+
path=str(package_json) if status else f"{package_json} {'; '.join(details)}",
|
|
492
479
|
suggestion=suggestion,
|
|
493
480
|
)
|
|
494
481
|
|
|
@@ -498,7 +485,11 @@ def _check_domain_migration_scaffold(
|
|
|
498
485
|
) -> CheckResult:
|
|
499
486
|
project_json = domain_dir / "project.json"
|
|
500
487
|
project = _load_json(project_json) or {}
|
|
501
|
-
targets =
|
|
488
|
+
targets = (
|
|
489
|
+
project.get("targets", {})
|
|
490
|
+
if isinstance(project.get("targets", {}), dict)
|
|
491
|
+
else {}
|
|
492
|
+
)
|
|
502
493
|
migrate_target = targets.get("migrate") if isinstance(targets, dict) else None
|
|
503
494
|
|
|
504
495
|
alembic_ini = domain_dir / "alembic.ini"
|
|
@@ -521,16 +512,19 @@ def _check_domain_migration_scaffold(
|
|
|
521
512
|
suggestion=f"rpr generate domain {name} --migrations",
|
|
522
513
|
)
|
|
523
514
|
|
|
524
|
-
options =
|
|
515
|
+
options = (
|
|
516
|
+
migrate_target.get("options", {}) if isinstance(migrate_target, dict) else {}
|
|
517
|
+
)
|
|
525
518
|
command_ok = isinstance(options, dict) and options.get("command") == (
|
|
526
|
-
"uv run alembic -c packages/python/
|
|
519
|
+
f"uv run alembic -c packages/python/{name_underscore}_domain/alembic.ini"
|
|
527
520
|
)
|
|
528
521
|
cwd_ok = isinstance(options, dict) and options.get("cwd") == "."
|
|
529
522
|
env_ok = False
|
|
530
523
|
if env_py.exists():
|
|
531
524
|
env_content = env_py.read_text()
|
|
532
525
|
env_ok = (
|
|
533
|
-
f"from {name_underscore}_domain.config.settings import Settings"
|
|
526
|
+
f"from {name_underscore}_domain.config.settings import Settings"
|
|
527
|
+
in env_content
|
|
534
528
|
and f"import {name_underscore}_domain.entities" in env_content
|
|
535
529
|
)
|
|
536
530
|
|
|
@@ -559,9 +553,7 @@ def _check_domain_migration_scaffold(
|
|
|
559
553
|
)
|
|
560
554
|
|
|
561
555
|
|
|
562
|
-
def _check_engine_install_metadata(
|
|
563
|
-
*, engine_dir: Path, suggestion: str
|
|
564
|
-
) -> CheckResult:
|
|
556
|
+
def _check_engine_install_metadata(*, engine_dir: Path, suggestion: str) -> CheckResult:
|
|
565
557
|
pyproject = engine_dir / "pyproject.toml"
|
|
566
558
|
data = _load_toml(pyproject)
|
|
567
559
|
if data is None:
|
|
@@ -574,7 +566,9 @@ def _check_engine_install_metadata(
|
|
|
574
566
|
)
|
|
575
567
|
|
|
576
568
|
build_system = data.get("build-system", {})
|
|
577
|
-
requires =
|
|
569
|
+
requires = (
|
|
570
|
+
build_system.get("requires", []) if isinstance(build_system, dict) else []
|
|
571
|
+
)
|
|
578
572
|
requires_set = set(requires) if isinstance(requires, list) else set()
|
|
579
573
|
status = MATURIN_SPEC in requires_set
|
|
580
574
|
return CheckResult(
|
|
@@ -10,6 +10,7 @@ from rich.console import Console
|
|
|
10
10
|
from rpr.cli import generate_app
|
|
11
11
|
from rpr.context import RunContext
|
|
12
12
|
from rpr.dependencies import api_runtime_dependencies
|
|
13
|
+
from rpr.dependencies import python_project_name
|
|
13
14
|
from rpr.workspace import add_workspace_member
|
|
14
15
|
|
|
15
16
|
console = Console()
|
|
@@ -29,11 +30,10 @@ def api(
|
|
|
29
30
|
name = typer.prompt("App name")
|
|
30
31
|
|
|
31
32
|
ctx = RunContext(dry_run=dry_run, project_dir=Path.cwd())
|
|
32
|
-
app_name =
|
|
33
|
-
|
|
34
|
-
domain_underscore = f"{name}_domain".replace("-", "_")
|
|
33
|
+
app_name = python_project_name(name, "api")
|
|
34
|
+
domain_name = python_project_name(name, "domain")
|
|
35
35
|
api_root = ctx.project_dir / "apps" / app_name
|
|
36
|
-
src_root = api_root / "src" /
|
|
36
|
+
src_root = api_root / "src" / app_name
|
|
37
37
|
tests_root = api_root / "tests"
|
|
38
38
|
|
|
39
39
|
console.print(f"\n[bold]Generating FastAPI app:[/] {app_name}\n")
|
|
@@ -41,14 +41,14 @@ def api(
|
|
|
41
41
|
ctx.ensure_dir(src_root / "routes")
|
|
42
42
|
ctx.ensure_dir(tests_root)
|
|
43
43
|
|
|
44
|
-
_write_api_pyproject(ctx, api_root, name, app_name,
|
|
44
|
+
_write_api_pyproject(ctx, api_root, name, app_name, domain_name)
|
|
45
45
|
_write_api_readme(ctx, api_root, name)
|
|
46
|
-
_write_api_project_json(ctx, api_root, app_name
|
|
47
|
-
_write_main(ctx, src_root / "main.py", name,
|
|
46
|
+
_write_api_project_json(ctx, api_root, app_name)
|
|
47
|
+
_write_main(ctx, src_root / "main.py", name, domain_name)
|
|
48
48
|
_write_init_file(ctx, src_root / "__init__.py")
|
|
49
49
|
_write_init_file(ctx, src_root / "routes" / "__init__.py")
|
|
50
50
|
_write_health_route(ctx, src_root / "routes" / "health.py")
|
|
51
|
-
_write_health_test(ctx, tests_root / "test_health.py",
|
|
51
|
+
_write_health_test(ctx, tests_root / "test_health.py", app_name)
|
|
52
52
|
|
|
53
53
|
add_workspace_member(ctx, f"apps/{app_name}")
|
|
54
54
|
ctx.preview_dependencies(
|
|
@@ -58,7 +58,8 @@ def api(
|
|
|
58
58
|
)
|
|
59
59
|
|
|
60
60
|
if not dry_run:
|
|
61
|
-
ctx.
|
|
61
|
+
ctx.run_uv_command(["uv", "add", *api_runtime_dependencies(name)], cwd=api_root)
|
|
62
|
+
ctx.run_uv_command(["uv", "sync", "--all-packages"], cwd=ctx.project_dir)
|
|
62
63
|
|
|
63
64
|
console.print(f"\n[bold green]Done![/] FastAPI app created at {api_root}")
|
|
64
65
|
console.print(f" Run with: npx nx serve {app_name}")
|
|
@@ -69,7 +70,7 @@ def _write_init_file(ctx: RunContext, path: Path) -> None:
|
|
|
69
70
|
|
|
70
71
|
|
|
71
72
|
def _write_api_pyproject(
|
|
72
|
-
ctx: RunContext, api_root: Path, name: str, app_name: str,
|
|
73
|
+
ctx: RunContext, api_root: Path, name: str, app_name: str, domain_name: str
|
|
73
74
|
) -> None:
|
|
74
75
|
content = f"""[project]
|
|
75
76
|
name = "{app_name}"
|
|
@@ -77,21 +78,17 @@ version = "0.1.0"
|
|
|
77
78
|
description = "{name} API"
|
|
78
79
|
readme = "README.md"
|
|
79
80
|
requires-python = ">=3.12"
|
|
80
|
-
dependencies = [
|
|
81
|
-
"{api_runtime_dependencies(name)[0]}",
|
|
82
|
-
"{api_runtime_dependencies(name)[1]}",
|
|
83
|
-
"{api_runtime_dependencies(name)[2]}",
|
|
84
|
-
]
|
|
81
|
+
dependencies = []
|
|
85
82
|
|
|
86
83
|
[build-system]
|
|
87
84
|
requires = ["hatchling"]
|
|
88
85
|
build-backend = "hatchling.build"
|
|
89
86
|
|
|
90
87
|
[tool.hatch.build.targets.wheel]
|
|
91
|
-
packages = ["src/{
|
|
88
|
+
packages = ["src/{app_name}"]
|
|
92
89
|
|
|
93
90
|
[tool.uv.sources]
|
|
94
|
-
{
|
|
91
|
+
{domain_name} = {{ workspace = true }}
|
|
95
92
|
|
|
96
93
|
[tool.pytest.ini_options]
|
|
97
94
|
testpaths = ["tests"]
|
|
@@ -107,9 +104,7 @@ FastAPI application generated by RPR.
|
|
|
107
104
|
ctx.write_file(api_root / "README.md", content)
|
|
108
105
|
|
|
109
106
|
|
|
110
|
-
def _write_api_project_json(
|
|
111
|
-
ctx: RunContext, api_root: Path, app_name: str, app_name_underscore: str
|
|
112
|
-
) -> None:
|
|
107
|
+
def _write_api_project_json(ctx: RunContext, api_root: Path, app_name: str) -> None:
|
|
113
108
|
project = {
|
|
114
109
|
"name": app_name,
|
|
115
110
|
"root": f"apps/{app_name}",
|
|
@@ -117,7 +112,7 @@ def _write_api_project_json(
|
|
|
117
112
|
"serve": {
|
|
118
113
|
"executor": "nx:run-commands",
|
|
119
114
|
"options": {
|
|
120
|
-
"command": f"uv run uvicorn {
|
|
115
|
+
"command": f"uv run uvicorn {app_name}.main:app --reload --host 0.0.0.0 --port 8000",
|
|
121
116
|
"cwd": f"apps/{app_name}",
|
|
122
117
|
},
|
|
123
118
|
},
|