devctl 1.1.0__tar.gz → 1.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. {devctl-1.1.0 → devctl-1.2.2}/PKG-INFO +33 -4
  2. {devctl-1.1.0 → devctl-1.2.2}/README.md +30 -3
  3. {devctl-1.1.0 → devctl-1.2.2}/devctl/commands/add.py +11 -11
  4. {devctl-1.1.0 → devctl-1.2.2}/devctl/commands/deploy.py +2 -1
  5. {devctl-1.1.0 → devctl-1.2.2}/devctl/commands/docker.py +1 -1
  6. {devctl-1.1.0 → devctl-1.2.2}/devctl/commands/init.py +0 -3
  7. {devctl-1.1.0 → devctl-1.2.2}/devctl/commands/run.py +1 -1
  8. devctl-1.2.2/devctl/commands/tui.py +32 -0
  9. devctl-1.2.2/devctl/generators/angular/__init__.py +8 -0
  10. devctl-1.1.0/devctl/generators/angular.py → devctl-1.2.2/devctl/generators/angular/generator.py +3 -2
  11. devctl-1.1.0/devctl/generators/scaffold_angular.py → devctl-1.2.2/devctl/generators/angular/scaffolder.py +1 -1
  12. devctl-1.2.2/devctl/generators/django/__init__.py +8 -0
  13. devctl-1.1.0/devctl/generators/django.py → devctl-1.2.2/devctl/generators/django/generator.py +8 -7
  14. devctl-1.1.0/devctl/generators/scaffold_django.py → devctl-1.2.2/devctl/generators/django/scaffolder.py +16 -28
  15. devctl-1.2.2/devctl/generators/django/templates/config/requirements.txt.j2 +3 -0
  16. devctl-1.2.2/devctl/generators/django/templates/resource/model.py.j2 +7 -0
  17. devctl-1.2.2/devctl/generators/django/templates/resource/serializer.py.j2 +4 -0
  18. devctl-1.2.2/devctl/generators/django/templates/resource/view.py.j2 +7 -0
  19. devctl-1.2.2/devctl/generators/docker/__init__.py +19 -0
  20. devctl-1.1.0/devctl/generators/docker_scaffold.py → devctl-1.2.2/devctl/generators/docker/scaffolder.py +2 -2
  21. devctl-1.2.2/devctl/generators/fastapi/__init__.py +8 -0
  22. devctl-1.1.0/devctl/generators/fastapi.py → devctl-1.2.2/devctl/generators/fastapi/generator.py +11 -21
  23. devctl-1.1.0/devctl/generators/scaffold_fastapi.py → devctl-1.2.2/devctl/generators/fastapi/scaffolder.py +14 -35
  24. devctl-1.2.2/devctl/generators/fastapi/templates/config/main.py.j2 +11 -0
  25. devctl-1.2.2/devctl/generators/fastapi/templates/config/requirements.txt.j2 +3 -0
  26. devctl-1.2.2/devctl/generators/fastapi/templates/resource/router.py.j2 +16 -0
  27. devctl-1.2.2/devctl/generators/fastapi/templates/resource/schema.py.j2 +15 -0
  28. devctl-1.2.2/devctl/generators/go_fiber/__init__.py +8 -0
  29. devctl-1.1.0/devctl/generators/go_fiber.py → devctl-1.2.2/devctl/generators/go_fiber/generator.py +7 -18
  30. devctl-1.1.0/devctl/generators/scaffold_go.py → devctl-1.2.2/devctl/generators/go_fiber/scaffolder.py +14 -23
  31. devctl-1.2.2/devctl/generators/go_fiber/templates/config/main.go.j2 +16 -0
  32. devctl-1.2.2/devctl/generators/go_fiber/templates/resource/handler.go.j2 +13 -0
  33. devctl-1.2.2/devctl/generators/go_fiber/templates/resource/model.go.j2 +6 -0
  34. devctl-1.2.2/devctl/generators/nestjs/__init__.py +8 -0
  35. devctl-1.1.0/devctl/generators/nestjs.py → devctl-1.2.2/devctl/generators/nestjs/generator.py +1 -0
  36. devctl-1.1.0/devctl/generators/scaffold_nestjs.py → devctl-1.2.2/devctl/generators/nestjs/scaffolder.py +1 -0
  37. devctl-1.2.2/devctl/generators/nextjs/__init__.py +8 -0
  38. devctl-1.1.0/devctl/generators/nextjs.py → devctl-1.2.2/devctl/generators/nextjs/generator.py +1 -0
  39. devctl-1.1.0/devctl/generators/scaffold_nextjs.py → devctl-1.2.2/devctl/generators/nextjs/scaffolder.py +13 -29
  40. devctl-1.2.2/devctl/generators/nextjs/templates/resource/component.tsx.j2 +14 -0
  41. devctl-1.2.2/devctl/generators/nextjs/templates/resource/page.tsx.j2 +11 -0
  42. devctl-1.2.2/devctl/generators/nodejs/__init__.py +8 -0
  43. devctl-1.1.0/devctl/generators/nodejs.py → devctl-1.2.2/devctl/generators/nodejs/generator.py +9 -21
  44. devctl-1.1.0/devctl/generators/scaffold_nodejs.py → devctl-1.2.2/devctl/generators/nodejs/scaffolder.py +13 -36
  45. devctl-1.2.2/devctl/generators/nodejs/templates/config/index.ts.j2 +17 -0
  46. devctl-1.2.2/devctl/generators/nodejs/templates/resource/controller.ts.j2 +18 -0
  47. devctl-1.2.2/devctl/generators/nodejs/templates/resource/routes.ts.j2 +10 -0
  48. devctl-1.2.2/devctl/generators/react/__init__.py +8 -0
  49. devctl-1.1.0/devctl/generators/react.py → devctl-1.2.2/devctl/generators/react/generator.py +1 -0
  50. devctl-1.1.0/devctl/generators/scaffold_react.py → devctl-1.2.2/devctl/generators/react/scaffolder.py +15 -36
  51. devctl-1.2.2/devctl/generators/react/templates/resource/component.tsx.j2 +19 -0
  52. devctl-1.2.2/devctl/generators/react/templates/resource/service.ts.j2 +13 -0
  53. devctl-1.2.2/devctl/generators/spring/__init__.py +11 -0
  54. devctl-1.1.0/devctl/generators/spring.py → devctl-1.2.2/devctl/generators/spring/generator.py +1 -1
  55. devctl-1.1.0/devctl/generators/scaffold_spring.py → devctl-1.2.2/devctl/generators/spring/scaffolder.py +2 -2
  56. devctl-1.2.2/devctl/generators/svelte/__init__.py +8 -0
  57. devctl-1.1.0/devctl/generators/svelte.py → devctl-1.2.2/devctl/generators/svelte/generator.py +1 -0
  58. devctl-1.1.0/devctl/generators/scaffold_svelte.py → devctl-1.2.2/devctl/generators/svelte/scaffolder.py +14 -29
  59. devctl-1.2.2/devctl/generators/svelte/templates/resource/component.svelte.j2 +18 -0
  60. devctl-1.2.2/devctl/generators/svelte/templates/resource/page.svelte.j2 +7 -0
  61. devctl-1.2.2/devctl/generators/vue/__init__.py +8 -0
  62. devctl-1.1.0/devctl/generators/vue.py → devctl-1.2.2/devctl/generators/vue/generator.py +3 -1
  63. devctl-1.1.0/devctl/generators/scaffold_vue.py → devctl-1.2.2/devctl/generators/vue/scaffolder.py +2 -2
  64. {devctl-1.1.0 → devctl-1.2.2}/devctl/main.py +2 -1
  65. devctl-1.2.2/devctl/orchestrator/process_manager.py +261 -0
  66. {devctl-1.1.0 → devctl-1.2.2}/devctl/orchestrator/runner.py +1 -1
  67. devctl-1.2.2/devctl/tui/app.py +810 -0
  68. {devctl-1.1.0 → devctl-1.2.2}/devctl/utils/dependencies.py +1 -0
  69. {devctl-1.1.0 → devctl-1.2.2}/devctl.egg-info/PKG-INFO +33 -4
  70. devctl-1.2.2/devctl.egg-info/SOURCES.txt +142 -0
  71. {devctl-1.1.0 → devctl-1.2.2}/devctl.egg-info/requires.txt +2 -0
  72. {devctl-1.1.0 → devctl-1.2.2}/pyproject.toml +5 -3
  73. {devctl-1.1.0 → devctl-1.2.2}/test/test_env_loader.py +6 -6
  74. {devctl-1.1.0 → devctl-1.2.2}/test/test_platform.py +2 -6
  75. {devctl-1.1.0 → devctl-1.2.2}/test/test_runner.py +1 -1
  76. devctl-1.2.2/test/test_tui.py +90 -0
  77. devctl-1.1.0/devctl/templates/angular/config/proxy.conf.json.j2 +0 -8
  78. devctl-1.1.0/devctl.egg-info/SOURCES.txt +0 -117
  79. devctl-1.1.0/test/test_django.py +0 -43
  80. devctl-1.1.0/test/test_docker_scaffold.py +0 -136
  81. devctl-1.1.0/test/test_fastapi.py +0 -41
  82. devctl-1.1.0/test/test_go.py +0 -40
  83. devctl-1.1.0/test/test_nestjs.py +0 -46
  84. devctl-1.1.0/test/test_nextjs.py +0 -40
  85. devctl-1.1.0/test/test_nodejs.py +0 -40
  86. devctl-1.1.0/test/test_pom_patcher.py +0 -52
  87. devctl-1.1.0/test/test_react.py +0 -44
  88. devctl-1.1.0/test/test_svelte.py +0 -40
  89. {devctl-1.1.0 → devctl-1.2.2}/LICENSE +0 -0
  90. {devctl-1.1.0 → devctl-1.2.2}/devctl/__init__.py +0 -0
  91. {devctl-1.1.0 → devctl-1.2.2}/devctl/commands/__init__.py +0 -0
  92. {devctl-1.1.0 → devctl-1.2.2}/devctl/generators/__init__.py +0 -0
  93. {devctl-1.1.0/devctl/templates/angular → devctl-1.2.2/devctl/generators/angular/templates}/config/environment.development.ts.j2 +0 -0
  94. {devctl-1.1.0/devctl/templates/angular → devctl-1.2.2/devctl/generators/angular/templates}/config/environment.ts.j2 +0 -0
  95. {devctl-1.1.0/devctl/templates → devctl-1.2.2/devctl/generators/angular/templates/config}/proxy.conf.json.j2 +0 -0
  96. {devctl-1.1.0/devctl/templates/angular → devctl-1.2.2/devctl/generators/angular/templates}/feature/models/request.model.ts.j2 +0 -0
  97. {devctl-1.1.0/devctl/templates/angular → devctl-1.2.2/devctl/generators/angular/templates}/feature/models/response.model.ts.j2 +0 -0
  98. {devctl-1.1.0/devctl/templates/angular → devctl-1.2.2/devctl/generators/angular/templates}/feature/pages/form/form.component.html.j2 +0 -0
  99. {devctl-1.1.0/devctl/templates/angular → devctl-1.2.2/devctl/generators/angular/templates}/feature/pages/form/form.component.scss.j2 +0 -0
  100. {devctl-1.1.0/devctl/templates/angular → devctl-1.2.2/devctl/generators/angular/templates}/feature/pages/form/form.component.ts.j2 +0 -0
  101. {devctl-1.1.0/devctl/templates/angular → devctl-1.2.2/devctl/generators/angular/templates}/feature/pages/list/list.component.html.j2 +0 -0
  102. {devctl-1.1.0/devctl/templates/angular → devctl-1.2.2/devctl/generators/angular/templates}/feature/pages/list/list.component.scss.j2 +0 -0
  103. {devctl-1.1.0/devctl/templates/angular → devctl-1.2.2/devctl/generators/angular/templates}/feature/pages/list/list.component.ts.j2 +0 -0
  104. {devctl-1.1.0/devctl/templates/angular → devctl-1.2.2/devctl/generators/angular/templates}/feature/routes.ts.j2 +0 -0
  105. {devctl-1.1.0/devctl/templates/angular → devctl-1.2.2/devctl/generators/angular/templates}/feature/services/service.ts.j2 +0 -0
  106. {devctl-1.1.0/devctl/templates/docker → devctl-1.2.2/devctl/generators/docker/templates}/deploy.yml.j2 +0 -0
  107. {devctl-1.1.0/devctl/templates/docker → devctl-1.2.2/devctl/generators/docker/templates}/django/Dockerfile.j2 +0 -0
  108. {devctl-1.1.0/devctl/templates/docker → devctl-1.2.2/devctl/generators/docker/templates}/fastapi/Dockerfile.j2 +0 -0
  109. {devctl-1.1.0/devctl/templates/docker → devctl-1.2.2/devctl/generators/docker/templates}/frontend/Dockerfile.j2 +0 -0
  110. {devctl-1.1.0/devctl/templates/docker → devctl-1.2.2/devctl/generators/docker/templates}/go/Dockerfile.j2 +0 -0
  111. {devctl-1.1.0/devctl/templates/docker → devctl-1.2.2/devctl/generators/docker/templates}/nestjs/Dockerfile.j2 +0 -0
  112. {devctl-1.1.0/devctl/templates/docker → devctl-1.2.2/devctl/generators/docker/templates}/nextjs/Dockerfile.j2 +0 -0
  113. {devctl-1.1.0/devctl/templates/docker → devctl-1.2.2/devctl/generators/docker/templates}/nodejs/Dockerfile.j2 +0 -0
  114. {devctl-1.1.0/devctl/templates/docker → devctl-1.2.2/devctl/generators/docker/templates}/spring/Dockerfile.j2 +0 -0
  115. {devctl-1.1.0/devctl/templates/docker → devctl-1.2.2/devctl/generators/docker/templates}/svelte/Dockerfile.j2 +0 -0
  116. {devctl-1.1.0/devctl/templates/spring → devctl-1.2.2/devctl/generators/spring/templates}/Controller.java.j2 +0 -0
  117. {devctl-1.1.0/devctl/templates/spring → devctl-1.2.2/devctl/generators/spring/templates}/Entity.java.j2 +0 -0
  118. {devctl-1.1.0/devctl/templates/spring → devctl-1.2.2/devctl/generators/spring/templates}/Repository.java.j2 +0 -0
  119. {devctl-1.1.0/devctl/templates/spring → devctl-1.2.2/devctl/generators/spring/templates}/Service.java.j2 +0 -0
  120. {devctl-1.1.0/devctl/templates/spring → devctl-1.2.2/devctl/generators/spring/templates}/ServiceImpl.java.j2 +0 -0
  121. {devctl-1.1.0/devctl/templates/spring → devctl-1.2.2/devctl/generators/spring/templates}/application.properties.j2 +0 -0
  122. {devctl-1.1.0/devctl/templates/spring → devctl-1.2.2/devctl/generators/spring/templates}/config/ApplicationConfig.java.j2 +0 -0
  123. {devctl-1.1.0/devctl/templates/spring → devctl-1.2.2/devctl/generators/spring/templates}/config/JwtAuthenticationFilter.java.j2 +0 -0
  124. {devctl-1.1.0/devctl/templates/spring → devctl-1.2.2/devctl/generators/spring/templates}/config/JwtService.java.j2 +0 -0
  125. {devctl-1.1.0/devctl/templates/spring → devctl-1.2.2/devctl/generators/spring/templates}/config/SecurityConfig.java.j2 +0 -0
  126. {devctl-1.1.0/devctl/templates/spring → devctl-1.2.2/devctl/generators/spring/templates}/docker-compose.yml.j2 +0 -0
  127. {devctl-1.1.0/devctl/templates/spring → devctl-1.2.2/devctl/generators/spring/templates}/dto/Request.java.j2 +0 -0
  128. {devctl-1.1.0/devctl/templates/spring → devctl-1.2.2/devctl/generators/spring/templates}/dto/Response.java.j2 +0 -0
  129. {devctl-1.1.0/devctl/templates/spring → devctl-1.2.2/devctl/generators/spring/templates}/mapper/Mapper.java.j2 +0 -0
  130. {devctl-1.1.0/devctl/templates/vue → devctl-1.2.2/devctl/generators/vue/templates}/config/App.vue.j2 +0 -0
  131. {devctl-1.1.0/devctl/templates/vue → devctl-1.2.2/devctl/generators/vue/templates}/config/main.ts.j2 +0 -0
  132. {devctl-1.1.0/devctl/templates/vue → devctl-1.2.2/devctl/generators/vue/templates}/config/router.ts.j2 +0 -0
  133. {devctl-1.1.0/devctl/templates/vue → devctl-1.2.2/devctl/generators/vue/templates}/config/vite.config.ts.j2 +0 -0
  134. {devctl-1.1.0/devctl/templates/vue → devctl-1.2.2/devctl/generators/vue/templates}/feature/Form.vue.j2 +0 -0
  135. {devctl-1.1.0/devctl/templates/vue → devctl-1.2.2/devctl/generators/vue/templates}/feature/List.vue.j2 +0 -0
  136. {devctl-1.1.0/devctl/templates/vue → devctl-1.2.2/devctl/generators/vue/templates}/feature/models.ts.j2 +0 -0
  137. {devctl-1.1.0/devctl/templates/vue → devctl-1.2.2/devctl/generators/vue/templates}/feature/routes.ts.j2 +0 -0
  138. {devctl-1.1.0/devctl/templates/vue → devctl-1.2.2/devctl/generators/vue/templates}/feature/service.ts.j2 +0 -0
  139. {devctl-1.1.0 → devctl-1.2.2}/devctl/orchestrator/__init__.py +0 -0
  140. {devctl-1.1.0 → devctl-1.2.2}/devctl/orchestrator/config_builder.py +0 -0
  141. {devctl-1.1.0 → devctl-1.2.2}/devctl/orchestrator/scanner.py +0 -0
  142. {devctl-1.1.0 → devctl-1.2.2}/devctl/utils/__init__.py +0 -0
  143. {devctl-1.1.0 → devctl-1.2.2}/devctl/utils/env_loader.py +0 -0
  144. {devctl-1.1.0 → devctl-1.2.2}/devctl/utils/platform.py +0 -0
  145. {devctl-1.1.0 → devctl-1.2.2}/devctl.egg-info/dependency_links.txt +0 -0
  146. {devctl-1.1.0 → devctl-1.2.2}/devctl.egg-info/entry_points.txt +0 -0
  147. {devctl-1.1.0 → devctl-1.2.2}/devctl.egg-info/top_level.txt +0 -0
  148. {devctl-1.1.0 → devctl-1.2.2}/setup.cfg +0 -0
  149. {devctl-1.1.0 → devctl-1.2.2}/test/test_add.py +0 -0
  150. {devctl-1.1.0 → devctl-1.2.2}/test/test_commands.py +0 -0
  151. {devctl-1.1.0 → devctl-1.2.2}/test/test_deploy.py +0 -0
  152. {devctl-1.1.0 → devctl-1.2.2}/test/test_init.py +0 -0
  153. {devctl-1.1.0 → devctl-1.2.2}/test/test_main.py +0 -0
  154. {devctl-1.1.0 → devctl-1.2.2}/test/test_mongodb.py +0 -0
  155. {devctl-1.1.0 → devctl-1.2.2}/test/test_scanner.py +0 -0
  156. {devctl-1.1.0 → devctl-1.2.2}/test/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devctl
3
- Version: 1.1.0
3
+ Version: 1.2.2
4
4
  Summary: Local development orchestrator for Spring Boot, Angular, and Vue.js
5
5
  Author: Youssef Fellah
6
6
  License: MIT License
@@ -37,6 +37,8 @@ Requires-Dist: requests>=2.31.0
37
37
  Requires-Dist: jinja2>=3.1.3
38
38
  Requires-Dist: rich>=13.7.0
39
39
  Requires-Dist: pyyaml>=6.0.1
40
+ Requires-Dist: textual>=0.80.0
41
+ Requires-Dist: psutil>=5.9.0
40
42
  Dynamic: license-file
41
43
 
42
44
  # devctl
@@ -59,15 +61,40 @@ containerization across Linux, macOS, and Windows.
59
61
  - **Instant Infrastructure**: Automatically generate optimized, multi-stage
60
62
  `Dockerfiles` and global `docker-compose-prod.yml` configurations by scanning
61
63
  your project tree.
64
+ - **Interactive Dashboard**: Real-time system monitoring (CPU/RAM/Disk) and service orchestration with side-by-side log streaming (`devctl tui`).
62
65
  - **Security by Default**: Inject standardized JWT authentication and security
63
66
  configurations into new projects.
64
67
 
68
+ ## Interactive Dashboard (TUI)
69
+
70
+ Launch the real-time terminal dashboard using `devctl tui`:
71
+
72
+ ### Dashboard & System Monitoring
73
+ ![Dashboard View](screenshots/tui_dashboard.png)
74
+
75
+ ### Real-Time Service Controls & Log Streaming
76
+ ![Services Control View](screenshots/tui_services_control.png)
77
+
78
+ <details>
79
+ <summary><b>View More TUI Views (Docker, Scaffolding, Project Init)</b></summary>
80
+
81
+ #### Docker Tools
82
+ ![Docker Scaffolding](screenshots/tui_docker_tools.png)
83
+
84
+ #### Vertical Resource Generator
85
+ ![Add Resource Generator](screenshots/tui_add_resource.png)
86
+
87
+ #### Project Initializer
88
+ ![Init Project Generator](screenshots/tui_init_project.png)
89
+
90
+ </details>
91
+
65
92
  ## Installation
66
93
 
67
94
  You can install `devctl` locally for development:
68
95
 
69
96
  ```bash
70
- git clone https://github.com/yss-ef/devctl.git
97
+ git clone https://github.com/ind4x/devctl.git
71
98
  cd devctl
72
99
  pip install -e .
73
100
  ```
@@ -110,8 +137,10 @@ devctl run
110
137
 
111
138
  ## Documentation
112
139
 
113
- For a detailed reference of all available commands and their options, see the
114
- [Commands Reference](COMMANDS.md).
140
+ * For a detailed reference of all available commands and their options, see the
141
+ [Commands Reference](COMMANDS.md).
142
+ * For an overview of the internal code structures and process pipelines, see the
143
+ [Architecture Guide](ARCHITECTURE.md).
115
144
 
116
145
  ## Contributing
117
146
 
@@ -18,15 +18,40 @@ containerization across Linux, macOS, and Windows.
18
18
  - **Instant Infrastructure**: Automatically generate optimized, multi-stage
19
19
  `Dockerfiles` and global `docker-compose-prod.yml` configurations by scanning
20
20
  your project tree.
21
+ - **Interactive Dashboard**: Real-time system monitoring (CPU/RAM/Disk) and service orchestration with side-by-side log streaming (`devctl tui`).
21
22
  - **Security by Default**: Inject standardized JWT authentication and security
22
23
  configurations into new projects.
23
24
 
25
+ ## Interactive Dashboard (TUI)
26
+
27
+ Launch the real-time terminal dashboard using `devctl tui`:
28
+
29
+ ### Dashboard & System Monitoring
30
+ ![Dashboard View](screenshots/tui_dashboard.png)
31
+
32
+ ### Real-Time Service Controls & Log Streaming
33
+ ![Services Control View](screenshots/tui_services_control.png)
34
+
35
+ <details>
36
+ <summary><b>View More TUI Views (Docker, Scaffolding, Project Init)</b></summary>
37
+
38
+ #### Docker Tools
39
+ ![Docker Scaffolding](screenshots/tui_docker_tools.png)
40
+
41
+ #### Vertical Resource Generator
42
+ ![Add Resource Generator](screenshots/tui_add_resource.png)
43
+
44
+ #### Project Initializer
45
+ ![Init Project Generator](screenshots/tui_init_project.png)
46
+
47
+ </details>
48
+
24
49
  ## Installation
25
50
 
26
51
  You can install `devctl` locally for development:
27
52
 
28
53
  ```bash
29
- git clone https://github.com/yss-ef/devctl.git
54
+ git clone https://github.com/ind4x/devctl.git
30
55
  cd devctl
31
56
  pip install -e .
32
57
  ```
@@ -69,8 +94,10 @@ devctl run
69
94
 
70
95
  ## Documentation
71
96
 
72
- For a detailed reference of all available commands and their options, see the
73
- [Commands Reference](COMMANDS.md).
97
+ * For a detailed reference of all available commands and their options, see the
98
+ [Commands Reference](COMMANDS.md).
99
+ * For an overview of the internal code structures and process pipelines, see the
100
+ [Architecture Guide](ARCHITECTURE.md).
74
101
 
75
102
  ## Contributing
76
103
 
@@ -8,17 +8,17 @@ import os
8
8
 
9
9
  import typer
10
10
 
11
- from devctl.generators.scaffold_angular import generate_angular_resource
12
- from devctl.generators.scaffold_django import generate_django_resource
13
- from devctl.generators.scaffold_fastapi import generate_fastapi_resource
14
- from devctl.generators.scaffold_go import generate_go_resource
15
- from devctl.generators.scaffold_nestjs import generate_nest_resource
16
- from devctl.generators.scaffold_nextjs import generate_nextjs_resource
17
- from devctl.generators.scaffold_nodejs import generate_nodejs_resource
18
- from devctl.generators.scaffold_react import generate_react_resource
19
- from devctl.generators.scaffold_spring import generate_spring_resource
20
- from devctl.generators.scaffold_svelte import generate_svelte_resource
21
- from devctl.generators.scaffold_vue import generate_vue_resource
11
+ from devctl.generators.angular import generate_angular_resource
12
+ from devctl.generators.django import generate_django_resource
13
+ from devctl.generators.fastapi import generate_fastapi_resource
14
+ from devctl.generators.go_fiber import generate_go_resource
15
+ from devctl.generators.nestjs import generate_nest_resource
16
+ from devctl.generators.nextjs import generate_nextjs_resource
17
+ from devctl.generators.nodejs import generate_nodejs_resource
18
+ from devctl.generators.react import generate_react_resource
19
+ from devctl.generators.spring import generate_spring_resource
20
+ from devctl.generators.svelte import generate_svelte_resource
21
+ from devctl.generators.vue import generate_vue_resource
22
22
  from devctl.orchestrator.scanner import detect_environment
23
23
  from devctl.utils.dependencies import check_tool
24
24
 
@@ -2,7 +2,7 @@ from pathlib import Path
2
2
 
3
3
  import typer
4
4
 
5
- from devctl.generators.docker_scaffold import (
5
+ from devctl.generators.docker import (
6
6
  DockerScaffoldError,
7
7
  scaffold_docker_assets,
8
8
  )
@@ -20,6 +20,7 @@ FORCE_OPTION = typer.Option(
20
20
  help="Overwrite generated Docker files that already exist.",
21
21
  )
22
22
 
23
+
23
24
  @app.command()
24
25
  def deploy(
25
26
  path: Path = PATH_ARGUMENT,
@@ -7,7 +7,7 @@ from pathlib import Path
7
7
 
8
8
  import typer
9
9
 
10
- from devctl.generators.docker_scaffold import (
10
+ from devctl.generators.docker import (
11
11
  DockerScaffoldError,
12
12
  scaffold_docker_assets,
13
13
  )
@@ -6,7 +6,6 @@ Django, Svelte, and Go.
6
6
 
7
7
  import typer
8
8
 
9
- # Angular generator
10
9
  from devctl.generators.angular import generate_angular_boilerplate
11
10
  from devctl.generators.django import generate_django_boilerplate
12
11
  from devctl.generators.fastapi import generate_fastapi_boilerplate
@@ -15,8 +14,6 @@ from devctl.generators.nestjs import generate_nest_boilerplate
15
14
  from devctl.generators.nextjs import generate_nextjs_boilerplate
16
15
  from devctl.generators.nodejs import generate_nodejs_boilerplate
17
16
  from devctl.generators.react import generate_react_boilerplate
18
-
19
- # Spring generator
20
17
  from devctl.generators.spring import download_spring_boilerplate
21
18
  from devctl.generators.svelte import generate_svelte_boilerplate
22
19
  from devctl.generators.vue import generate_vue_boilerplate
@@ -7,7 +7,7 @@ from pathlib import Path
7
7
 
8
8
  import typer
9
9
 
10
- from devctl.generators.docker_scaffold import discover_docker_projects
10
+ from devctl.generators.docker import discover_docker_projects
11
11
  from devctl.orchestrator.runner import launch_dev_environment
12
12
  from devctl.utils.dependencies import check_tool
13
13
 
@@ -0,0 +1,32 @@
1
+ """
2
+ CLI command group for launching the interactive TUI.
3
+ """
4
+
5
+ import typer
6
+
7
+ app = typer.Typer(help="Interactive Terminal User Interface.")
8
+
9
+
10
+ @app.callback(invoke_without_command=True)
11
+ def launch_tui(
12
+ ctx: typer.Context,
13
+ single: bool = typer.Option(
14
+ False, "--single", "-s", help="Launch the single-panel dashboard layout."
15
+ ),
16
+ ):
17
+ """
18
+ Launches the interactive btop-like management interface.
19
+ """
20
+ if ctx.invoked_subcommand is not None:
21
+ return
22
+
23
+ typer.secho("Initializing interactive Devctl TUI...", fg=typer.colors.CYAN)
24
+
25
+ try:
26
+ from devctl.tui.app import DevctlTUI
27
+
28
+ tui_app = DevctlTUI(single_panel=single)
29
+ tui_app.run()
30
+ except Exception as e:
31
+ typer.secho(f"Error launching TUI: {e}", fg=typer.colors.RED)
32
+ raise typer.Exit(code=1) from e
@@ -0,0 +1,8 @@
1
+ """
2
+ Angular framework generator and scaffolder.
3
+ """
4
+
5
+ from devctl.generators.angular.generator import generate_angular_boilerplate
6
+ from devctl.generators.angular.scaffolder import generate_angular_resource
7
+
8
+ __all__ = ["generate_angular_boilerplate", "generate_angular_resource"]
@@ -23,7 +23,7 @@ def setup_angular_environments(project_path: str):
23
23
  os.makedirs(env_dir, exist_ok=True)
24
24
 
25
25
  # 2. Template rendering via Jinja2
26
- templates_dir = os.path.join(os.path.dirname(__file__), "..", "templates", "angular", "config")
26
+ templates_dir = os.path.join(os.path.dirname(__file__), "templates", "config")
27
27
  env = Environment(loader=FileSystemLoader(templates_dir))
28
28
 
29
29
  files_to_generate = {
@@ -79,7 +79,8 @@ def generate_angular_boilerplate(project_name: str) -> bool:
79
79
 
80
80
  safe_name = project_name.lower().replace("_", "-")
81
81
 
82
- from devctl.utils import get_platform
82
+ from ...utils import get_platform
83
+
83
84
  platform = get_platform()
84
85
  try:
85
86
  subprocess.run(
@@ -117,7 +117,7 @@ def generate_angular_resource(resource_name: str, fields_str: str, root_path: st
117
117
  },
118
118
  ]
119
119
 
120
- templates_dir = os.path.join(os.path.dirname(__file__), "..", "templates", "angular", "feature")
120
+ templates_dir = os.path.join(os.path.dirname(__file__), "templates", "feature")
121
121
  env = Environment(loader=FileSystemLoader(templates_dir))
122
122
 
123
123
  typer.secho(f"Generating Angular feature '{entity_name}'...", fg=typer.colors.CYAN)
@@ -0,0 +1,8 @@
1
+ """
2
+ Django framework generator and scaffolder.
3
+ """
4
+
5
+ from devctl.generators.django.generator import generate_django_boilerplate
6
+ from devctl.generators.django.scaffolder import generate_django_resource
7
+
8
+ __all__ = ["generate_django_boilerplate", "generate_django_resource"]
@@ -5,8 +5,10 @@ Includes boilerplate generation with Django and DRF.
5
5
 
6
6
  import os
7
7
  import subprocess
8
+ import sys
8
9
 
9
10
  import typer
11
+ from jinja2 import Environment, FileSystemLoader
10
12
 
11
13
 
12
14
  def generate_django_boilerplate(project_name: str) -> bool:
@@ -20,15 +22,14 @@ def generate_django_boilerplate(project_name: str) -> bool:
20
22
  try:
21
23
  os.makedirs(project_path, exist_ok=True)
22
24
 
25
+ templates_dir = os.path.join(os.path.dirname(__file__), "templates", "config")
26
+ env = Environment(loader=FileSystemLoader(templates_dir))
27
+
23
28
  # 1. Create requirements.txt
24
- requirements = """django
25
- djangorestframework
26
- django-cors-headers
27
- """
28
- with open(os.path.join(project_path, "requirements.txt"), "w") as f:
29
- f.write(requirements)
29
+ req_content = env.get_template("requirements.txt.j2").render()
30
+ with open(os.path.join(project_path, "requirements.txt"), "w", encoding="utf-8") as f:
31
+ f.write(req_content)
30
32
 
31
- import sys
32
33
  python_exe = "python" if sys.platform == "win32" else "python3"
33
34
 
34
35
  # 2. Create virtual environment
@@ -6,6 +6,7 @@ Handles the creation of models, serializers, and views.
6
6
  import os
7
7
 
8
8
  import typer
9
+ from jinja2 import Environment, FileSystemLoader
9
10
 
10
11
  from devctl.orchestrator.scanner import detect_environment
11
12
 
@@ -30,47 +31,34 @@ def generate_django_resource(resource_name: str, fields_str: str, root_path: str
30
31
  if not os.path.exists(core_dir):
31
32
  os.makedirs(core_dir, exist_ok=True)
32
33
 
34
+ templates_dir = os.path.join(os.path.dirname(__file__), "templates", "resource")
35
+ env = Environment(loader=FileSystemLoader(templates_dir))
36
+
33
37
  typer.secho(f"⚙️ Generating Django resource '{entity_name}'...", fg=typer.colors.CYAN)
34
38
 
39
+ context = {
40
+ "entity_name": entity_name,
41
+ "fields_str": fields_str,
42
+ }
43
+
35
44
  # 1. Append Model
36
- model_snippet = f"""
37
- class {entity_name}(models.Model):
38
- # Fields: {fields_str}
39
- created_at = models.DateTimeField(auto_now_add=True)
40
- updated_at = models.DateTimeField(auto_now=True)
41
-
42
- def __str__(self):
43
- return f"{entity_name} {{self.id}}"
44
- """
45
- with open(os.path.join(core_dir, "models.py"), "a") as f:
45
+ model_snippet = "\n" + env.get_template("model.py.j2").render(**context) + "\n"
46
+ with open(os.path.join(core_dir, "models.py"), "a", encoding="utf-8") as f:
46
47
  f.write(model_snippet)
47
48
 
48
49
  # 2. Append Serializer
49
50
  serializer_path = os.path.join(core_dir, "serializers.py")
50
51
  if not os.path.exists(serializer_path):
51
- with open(serializer_path, "w") as f:
52
+ with open(serializer_path, "w", encoding="utf-8") as f:
52
53
  f.write("from rest_framework import serializers\nfrom .models import *\n")
53
54
 
54
- serializer_snippet = f"""
55
- class {entity_name}Serializer(serializers.ModelSerializer):
56
- class Meta:
57
- model = {entity_name}
58
- fields = '__all__'
59
- """
60
- with open(serializer_path, "a") as f:
55
+ serializer_snippet = "\n" + env.get_template("serializer.py.j2").render(**context) + "\n"
56
+ with open(serializer_path, "a", encoding="utf-8") as f:
61
57
  f.write(serializer_snippet)
62
58
 
63
59
  # 3. Append View
64
- view_snippet = f"""
65
- from rest_framework import viewsets
66
- from .models import {entity_name}
67
- from .serializers import {entity_name}Serializer
68
-
69
- class {entity_name}ViewSet(viewsets.ModelViewSet):
70
- queryset = {entity_name}.objects.all()
71
- serializer_class = {entity_name}Serializer
72
- """
73
- with open(os.path.join(core_dir, "views.py"), "a") as f:
60
+ view_snippet = "\n" + env.get_template("view.py.j2").render(**context) + "\n"
61
+ with open(os.path.join(core_dir, "views.py"), "a", encoding="utf-8") as f:
74
62
  f.write(view_snippet)
75
63
 
76
64
  typer.secho(f"✅ {entity_name} Django feature successfully generated!", fg=typer.colors.GREEN)
@@ -0,0 +1,3 @@
1
+ django
2
+ djangorestframework
3
+ django-cors-headers
@@ -0,0 +1,7 @@
1
+ class {{ entity_name }}(models.Model):
2
+ # Fields: {{ fields_str }}
3
+ created_at = models.DateTimeField(auto_now_add=True)
4
+ updated_at = models.DateTimeField(auto_now=True)
5
+
6
+ def __str__(self):
7
+ return f"{{ entity_name }} {self.id}"
@@ -0,0 +1,4 @@
1
+ class {{ entity_name }}Serializer(serializers.ModelSerializer):
2
+ class Meta:
3
+ model = {{ entity_name }}
4
+ fields = '__all__'
@@ -0,0 +1,7 @@
1
+ from rest_framework import viewsets
2
+ from .models import {{ entity_name }}
3
+ from .serializers import {{ entity_name }}Serializer
4
+
5
+ class {{ entity_name }}ViewSet(viewsets.ModelViewSet):
6
+ queryset = {{ entity_name }}.objects.all()
7
+ serializer_class = {{ entity_name }}Serializer
@@ -0,0 +1,19 @@
1
+ """
2
+ Docker asset scaffolder.
3
+ """
4
+
5
+ from devctl.generators.docker.scaffolder import (
6
+ DockerProject,
7
+ DockerScaffoldError,
8
+ discover_docker_projects,
9
+ sanitize_service_name,
10
+ scaffold_docker_assets,
11
+ )
12
+
13
+ __all__ = [
14
+ "DockerProject",
15
+ "DockerScaffoldError",
16
+ "discover_docker_projects",
17
+ "sanitize_service_name",
18
+ "scaffold_docker_assets",
19
+ ]
@@ -257,7 +257,7 @@ def _generate_compose_content(projects: list[DockerProject]) -> str:
257
257
 
258
258
  services_data.append(service_dict)
259
259
 
260
- template_dir = Path(__file__).resolve().parent.parent / "templates" / "docker"
260
+ template_dir = Path(__file__).resolve().parent / "templates"
261
261
  env = Environment(
262
262
  loader=FileSystemLoader(str(template_dir)),
263
263
  trim_blocks=True,
@@ -501,7 +501,7 @@ def _write_file(path: Path, content: str, *, force: bool, dry_run: bool) -> File
501
501
 
502
502
 
503
503
  def _template_environment() -> Environment:
504
- template_dir = Path(__file__).resolve().parent.parent / "templates" / "docker"
504
+ template_dir = Path(__file__).resolve().parent / "templates"
505
505
  return Environment(
506
506
  loader=FileSystemLoader(str(template_dir)),
507
507
  trim_blocks=True,
@@ -0,0 +1,8 @@
1
+ """
2
+ FastAPI framework generator and scaffolder.
3
+ """
4
+
5
+ from devctl.generators.fastapi.generator import generate_fastapi_boilerplate
6
+ from devctl.generators.fastapi.scaffolder import generate_fastapi_resource
7
+
8
+ __all__ = ["generate_fastapi_boilerplate", "generate_fastapi_resource"]
@@ -5,8 +5,10 @@ Includes boilerplate generation with Uvicorn and Pydantic.
5
5
 
6
6
  import os
7
7
  import subprocess
8
+ import sys
8
9
 
9
10
  import typer
11
+ from jinja2 import Environment, FileSystemLoader
10
12
 
11
13
 
12
14
  def generate_fastapi_boilerplate(project_name: str) -> bool:
@@ -20,31 +22,19 @@ def generate_fastapi_boilerplate(project_name: str) -> bool:
20
22
  try:
21
23
  os.makedirs(project_path, exist_ok=True)
22
24
 
23
- # 1. Create main.py
24
- main_py = """from fastapi import FastAPI
25
-
26
- app = FastAPI(title="devctl FastAPI project")
27
-
28
- @app.get("/")
29
- def read_root():
30
- return {"Hello": "from devctl FastAPI!"}
25
+ templates_dir = os.path.join(os.path.dirname(__file__), "templates", "config")
26
+ env = Environment(loader=FileSystemLoader(templates_dir))
31
27
 
32
- @app.get("/items/{item_id}")
33
- def read_item(item_id: int, q: str = None):
34
- return {"item_id": item_id, "q": q}
35
- """
36
- with open(os.path.join(project_path, "main.py"), "w") as f:
37
- f.write(main_py)
28
+ # 1. Create main.py
29
+ main_content = env.get_template("main.py.j2").render()
30
+ with open(os.path.join(project_path, "main.py"), "w", encoding="utf-8") as f:
31
+ f.write(main_content)
38
32
 
39
33
  # 2. Create requirements.txt
40
- requirements = """fastapi
41
- uvicorn[standard]
42
- pydantic
43
- """
44
- with open(os.path.join(project_path, "requirements.txt"), "w") as f:
45
- f.write(requirements)
34
+ req_content = env.get_template("requirements.txt.j2").render()
35
+ with open(os.path.join(project_path, "requirements.txt"), "w", encoding="utf-8") as f:
36
+ f.write(req_content)
46
37
 
47
- import sys
48
38
  python_exe = "python" if sys.platform == "win32" else "python3"
49
39
 
50
40
  # 3. Create virtual environment
@@ -6,6 +6,7 @@ Handles the creation of routers, schemas, and models.
6
6
  import os
7
7
 
8
8
  import typer
9
+ from jinja2 import Environment, FileSystemLoader
9
10
 
10
11
  from devctl.orchestrator.scanner import detect_environment
11
12
 
@@ -35,47 +36,25 @@ def generate_fastapi_resource(resource_name: str, fields_str: str, root_path: st
35
36
  with open(os.path.join(d, "__init__.py"), "a"):
36
37
  pass
37
38
 
38
- typer.secho(f"⚙️ Generating FastAPI resource '{entity_name}'...", fg=typer.colors.CYAN)
39
-
40
- # 1. Generate Schema (Pydantic)
41
- schema_content = f"""from pydantic import BaseModel
42
- from typing import Optional
39
+ templates_dir = os.path.join(os.path.dirname(__file__), "templates", "resource")
40
+ env = Environment(loader=FileSystemLoader(templates_dir))
43
41
 
44
- class {entity_name}Base(BaseModel):
45
- # Fields: {fields_str}
46
- pass
47
-
48
- class {entity_name}Create({entity_name}Base):
49
- pass
42
+ typer.secho(f"⚙️ Generating FastAPI resource '{entity_name}'...", fg=typer.colors.CYAN)
50
43
 
51
- class {entity_name}({entity_name}Base):
52
- id: int
44
+ context = {
45
+ "entity_name": entity_name,
46
+ "resource_lower": resource_lower,
47
+ "fields_str": fields_str,
48
+ }
53
49
 
54
- class Config:
55
- orm_mode = True
56
- """
57
- with open(os.path.join(schemas_dir, f"{resource_lower}.py"), "w") as f:
50
+ # 1. Generate Schema (Pydantic)
51
+ schema_content = env.get_template("schema.py.j2").render(**context)
52
+ with open(os.path.join(schemas_dir, f"{resource_lower}.py"), "w", encoding="utf-8") as f:
58
53
  f.write(schema_content)
59
54
 
60
55
  # 2. Generate Router
61
- router_content = f"""from fastapi import APIRouter, HTTPException
62
- from typing import List
63
- from schemas import {resource_lower} as schemas
64
-
65
- router = APIRouter(
66
- prefix="/{resource_lower}s",
67
- tags=["{resource_lower}s"]
68
- )
69
-
70
- @router.get("/", response_model=List[schemas.{entity_name}])
71
- def read_{resource_lower}s():
72
- return []
73
-
74
- @router.post("/", response_model=schemas.{entity_name})
75
- def create_{resource_lower}(item: schemas.{entity_name}Create):
76
- return {{"id": 1, **item.dict()}}
77
- """
78
- with open(os.path.join(routers_dir, f"{resource_lower}.py"), "w") as f:
56
+ router_content = env.get_template("router.py.j2").render(**context)
57
+ with open(os.path.join(routers_dir, f"{resource_lower}.py"), "w", encoding="utf-8") as f:
79
58
  f.write(router_content)
80
59
 
81
60
  typer.secho(f"{entity_name} FastAPI feature successfully generated!", fg=typer.colors.GREEN)
@@ -0,0 +1,11 @@
1
+ from fastapi import FastAPI
2
+
3
+ app = FastAPI(title="devctl FastAPI project")
4
+
5
+ @app.get("/")
6
+ def read_root():
7
+ return {"Hello": "from devctl FastAPI!"}
8
+
9
+ @app.get("/items/{item_id}")
10
+ def read_item(item_id: int, q: str = None):
11
+ return {"item_id": item_id, "q": q}
@@ -0,0 +1,3 @@
1
+ fastapi
2
+ uvicorn[standard]
3
+ pydantic
@@ -0,0 +1,16 @@
1
+ from fastapi import APIRouter, HTTPException
2
+ from typing import List
3
+ from schemas import {{ resource_lower }} as schemas
4
+
5
+ router = APIRouter(
6
+ prefix="/{{ resource_lower }}s",
7
+ tags=["{{ resource_lower }}s"]
8
+ )
9
+
10
+ @router.get("/", response_model=List[schemas.{{ entity_name }}])
11
+ def read_{{ resource_lower }}s():
12
+ return []
13
+
14
+ @router.post("/", response_model=schemas.{{ entity_name }})
15
+ def create_{{ resource_lower }}(item: schemas.{{ entity_name }}Create):
16
+ return {"id": 1, **item.dict()}
@@ -0,0 +1,15 @@
1
+ from pydantic import BaseModel
2
+ from typing import Optional
3
+
4
+ class {{ entity_name }}Base(BaseModel):
5
+ # Fields: {{ fields_str }}
6
+ pass
7
+
8
+ class {{ entity_name }}Create({{ entity_name }}Base):
9
+ pass
10
+
11
+ class {{ entity_name }}({{ entity_name }}Base):
12
+ id: int
13
+
14
+ class Config:
15
+ orm_mode = True
@@ -0,0 +1,8 @@
1
+ """
2
+ Go Fiber framework generator and scaffolder.
3
+ """
4
+
5
+ from devctl.generators.go_fiber.generator import generate_go_boilerplate
6
+ from devctl.generators.go_fiber.scaffolder import generate_go_resource
7
+
8
+ __all__ = ["generate_go_boilerplate", "generate_go_resource"]