@tdk-landscape/tdk-cli-core 1.3.14

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 (212) hide show
  1. package/README.md +293 -0
  2. package/bin/tdk.js +14 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +64 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/completion.d.ts +3 -0
  8. package/dist/commands/completion.d.ts.map +1 -0
  9. package/dist/commands/completion.js +294 -0
  10. package/dist/commands/completion.js.map +1 -0
  11. package/dist/commands/config.d.ts +3 -0
  12. package/dist/commands/config.d.ts.map +1 -0
  13. package/dist/commands/config.js +220 -0
  14. package/dist/commands/config.js.map +1 -0
  15. package/dist/commands/doctor.d.ts +3 -0
  16. package/dist/commands/doctor.d.ts.map +1 -0
  17. package/dist/commands/doctor.js +176 -0
  18. package/dist/commands/doctor.js.map +1 -0
  19. package/dist/commands/down.d.ts +3 -0
  20. package/dist/commands/down.d.ts.map +1 -0
  21. package/dist/commands/down.js +32 -0
  22. package/dist/commands/down.js.map +1 -0
  23. package/dist/commands/help.d.ts +2 -0
  24. package/dist/commands/help.d.ts.map +1 -0
  25. package/dist/commands/help.js +130 -0
  26. package/dist/commands/help.js.map +1 -0
  27. package/dist/commands/networks.d.ts +3 -0
  28. package/dist/commands/networks.d.ts.map +1 -0
  29. package/dist/commands/networks.js +260 -0
  30. package/dist/commands/networks.js.map +1 -0
  31. package/dist/commands/project.d.ts +3 -0
  32. package/dist/commands/project.d.ts.map +1 -0
  33. package/dist/commands/project.js +360 -0
  34. package/dist/commands/project.js.map +1 -0
  35. package/dist/commands/projects.d.ts +3 -0
  36. package/dist/commands/projects.d.ts.map +1 -0
  37. package/dist/commands/projects.js +71 -0
  38. package/dist/commands/projects.js.map +1 -0
  39. package/dist/commands/resource.d.ts +69 -0
  40. package/dist/commands/resource.d.ts.map +1 -0
  41. package/dist/commands/resource.js +572 -0
  42. package/dist/commands/resource.js.map +1 -0
  43. package/dist/commands/resources.d.ts +3 -0
  44. package/dist/commands/resources.d.ts.map +1 -0
  45. package/dist/commands/resources.js +73 -0
  46. package/dist/commands/resources.js.map +1 -0
  47. package/dist/commands/stack.d.ts +3 -0
  48. package/dist/commands/stack.d.ts.map +1 -0
  49. package/dist/commands/stack.js +103 -0
  50. package/dist/commands/stack.js.map +1 -0
  51. package/dist/commands/stacks.d.ts +3 -0
  52. package/dist/commands/stacks.d.ts.map +1 -0
  53. package/dist/commands/stacks.js +43 -0
  54. package/dist/commands/stacks.js.map +1 -0
  55. package/dist/commands/status.d.ts +3 -0
  56. package/dist/commands/status.d.ts.map +1 -0
  57. package/dist/commands/status.js +71 -0
  58. package/dist/commands/status.js.map +1 -0
  59. package/dist/commands/ui.d.ts +3 -0
  60. package/dist/commands/ui.d.ts.map +1 -0
  61. package/dist/commands/ui.js +446 -0
  62. package/dist/commands/ui.js.map +1 -0
  63. package/dist/commands/up.d.ts +3 -0
  64. package/dist/commands/up.d.ts.map +1 -0
  65. package/dist/commands/up.js +149 -0
  66. package/dist/commands/up.js.map +1 -0
  67. package/dist/commands/upgrade.d.ts +3 -0
  68. package/dist/commands/upgrade.d.ts.map +1 -0
  69. package/dist/commands/upgrade.js +454 -0
  70. package/dist/commands/upgrade.js.map +1 -0
  71. package/dist/commands/version.d.ts +3 -0
  72. package/dist/commands/version.d.ts.map +1 -0
  73. package/dist/commands/version.js +9 -0
  74. package/dist/commands/version.js.map +1 -0
  75. package/dist/components/Accessible.d.ts +8 -0
  76. package/dist/components/Accessible.d.ts.map +1 -0
  77. package/dist/components/Accessible.js +10 -0
  78. package/dist/components/Accessible.js.map +1 -0
  79. package/dist/components/BaseTooltip.d.ts +4 -0
  80. package/dist/components/BaseTooltip.d.ts.map +1 -0
  81. package/dist/components/BaseTooltip.js +28 -0
  82. package/dist/components/BaseTooltip.js.map +1 -0
  83. package/dist/components/DetailPanel.d.ts +4 -0
  84. package/dist/components/DetailPanel.d.ts.map +1 -0
  85. package/dist/components/DetailPanel.js +18 -0
  86. package/dist/components/DetailPanel.js.map +1 -0
  87. package/dist/components/FileTree.d.ts +4 -0
  88. package/dist/components/FileTree.d.ts.map +1 -0
  89. package/dist/components/FileTree.js +47 -0
  90. package/dist/components/FileTree.js.map +1 -0
  91. package/dist/components/ResourceSelectInput.d.ts +4 -0
  92. package/dist/components/ResourceSelectInput.d.ts.map +1 -0
  93. package/dist/components/ResourceSelectInput.js +7 -0
  94. package/dist/components/ResourceSelectInput.js.map +1 -0
  95. package/dist/components/ResourceTable.d.ts +4 -0
  96. package/dist/components/ResourceTable.d.ts.map +1 -0
  97. package/dist/components/ResourceTable.js +18 -0
  98. package/dist/components/ResourceTable.js.map +1 -0
  99. package/dist/components/TabBar.d.ts +4 -0
  100. package/dist/components/TabBar.d.ts.map +1 -0
  101. package/dist/components/TabBar.js +17 -0
  102. package/dist/components/TabBar.js.map +1 -0
  103. package/dist/components/Tooltip.d.ts +12 -0
  104. package/dist/components/Tooltip.d.ts.map +1 -0
  105. package/dist/components/Tooltip.js +12 -0
  106. package/dist/components/Tooltip.js.map +1 -0
  107. package/dist/components/index.d.ts +8 -0
  108. package/dist/components/index.d.ts.map +1 -0
  109. package/dist/components/index.js +8 -0
  110. package/dist/components/index.js.map +1 -0
  111. package/dist/config/platform-standards.d.ts +159 -0
  112. package/dist/config/platform-standards.d.ts.map +1 -0
  113. package/dist/config/platform-standards.js +181 -0
  114. package/dist/config/platform-standards.js.map +1 -0
  115. package/dist/generator/extension-fetch.d.ts +9 -0
  116. package/dist/generator/extension-fetch.d.ts.map +1 -0
  117. package/dist/generator/extension-fetch.js +153 -0
  118. package/dist/generator/extension-fetch.js.map +1 -0
  119. package/dist/generator/template-engine.d.ts +60 -0
  120. package/dist/generator/template-engine.d.ts.map +1 -0
  121. package/dist/generator/template-engine.js +416 -0
  122. package/dist/generator/template-engine.js.map +1 -0
  123. package/dist/index.d.ts +11 -0
  124. package/dist/index.d.ts.map +1 -0
  125. package/dist/index.js +11 -0
  126. package/dist/index.js.map +1 -0
  127. package/dist/types/index.d.ts +236 -0
  128. package/dist/types/index.d.ts.map +1 -0
  129. package/dist/types/index.js +17 -0
  130. package/dist/types/index.js.map +1 -0
  131. package/dist/utils/cache.d.ts +19 -0
  132. package/dist/utils/cache.d.ts.map +1 -0
  133. package/dist/utils/cache.js +64 -0
  134. package/dist/utils/cache.js.map +1 -0
  135. package/dist/utils/command-helpers.d.ts +17 -0
  136. package/dist/utils/command-helpers.d.ts.map +1 -0
  137. package/dist/utils/command-helpers.js +48 -0
  138. package/dist/utils/command-helpers.js.map +1 -0
  139. package/dist/utils/constants.d.ts +50 -0
  140. package/dist/utils/constants.d.ts.map +1 -0
  141. package/dist/utils/constants.js +100 -0
  142. package/dist/utils/constants.js.map +1 -0
  143. package/dist/utils/discovery-context.d.ts +4 -0
  144. package/dist/utils/discovery-context.d.ts.map +1 -0
  145. package/dist/utils/discovery-context.js +39 -0
  146. package/dist/utils/discovery-context.js.map +1 -0
  147. package/dist/utils/docker.d.ts +3 -0
  148. package/dist/utils/docker.d.ts.map +1 -0
  149. package/dist/utils/docker.js +13 -0
  150. package/dist/utils/docker.js.map +1 -0
  151. package/dist/utils/env-validator.d.ts +15 -0
  152. package/dist/utils/env-validator.d.ts.map +1 -0
  153. package/dist/utils/env-validator.js +95 -0
  154. package/dist/utils/env-validator.js.map +1 -0
  155. package/dist/utils/errors.d.ts +28 -0
  156. package/dist/utils/errors.d.ts.map +1 -0
  157. package/dist/utils/errors.js +127 -0
  158. package/dist/utils/errors.js.map +1 -0
  159. package/dist/utils/file-helpers.d.ts +14 -0
  160. package/dist/utils/file-helpers.d.ts.map +1 -0
  161. package/dist/utils/file-helpers.js +45 -0
  162. package/dist/utils/file-helpers.js.map +1 -0
  163. package/dist/utils/formatting.d.ts +30 -0
  164. package/dist/utils/formatting.d.ts.map +1 -0
  165. package/dist/utils/formatting.js +164 -0
  166. package/dist/utils/formatting.js.map +1 -0
  167. package/dist/utils/paths.d.ts +3 -0
  168. package/dist/utils/paths.d.ts.map +1 -0
  169. package/dist/utils/paths.js +41 -0
  170. package/dist/utils/paths.js.map +1 -0
  171. package/dist/utils/port-assignment.d.ts +6 -0
  172. package/dist/utils/port-assignment.d.ts.map +1 -0
  173. package/dist/utils/port-assignment.js +75 -0
  174. package/dist/utils/port-assignment.js.map +1 -0
  175. package/dist/utils/project-features.d.ts +23 -0
  176. package/dist/utils/project-features.d.ts.map +1 -0
  177. package/dist/utils/project-features.js +98 -0
  178. package/dist/utils/project-features.js.map +1 -0
  179. package/dist/utils/project-templates.d.ts +7 -0
  180. package/dist/utils/project-templates.d.ts.map +1 -0
  181. package/dist/utils/project-templates.js +24 -0
  182. package/dist/utils/project-templates.js.map +1 -0
  183. package/dist/utils/resource-features.d.ts +28 -0
  184. package/dist/utils/resource-features.d.ts.map +1 -0
  185. package/dist/utils/resource-features.js +148 -0
  186. package/dist/utils/resource-features.js.map +1 -0
  187. package/dist/utils/services.d.ts +18 -0
  188. package/dist/utils/services.d.ts.map +1 -0
  189. package/dist/utils/services.js +291 -0
  190. package/dist/utils/services.js.map +1 -0
  191. package/dist/utils/stack-features.d.ts +22 -0
  192. package/dist/utils/stack-features.d.ts.map +1 -0
  193. package/dist/utils/stack-features.js +13 -0
  194. package/dist/utils/stack-features.js.map +1 -0
  195. package/dist/utils/tar.d.ts +7 -0
  196. package/dist/utils/tar.d.ts.map +1 -0
  197. package/dist/utils/tar.js +21 -0
  198. package/dist/utils/tar.js.map +1 -0
  199. package/dist/utils/tilt.d.ts +18 -0
  200. package/dist/utils/tilt.d.ts.map +1 -0
  201. package/dist/utils/tilt.js +77 -0
  202. package/dist/utils/tilt.js.map +1 -0
  203. package/dist/utils/validation.d.ts +9 -0
  204. package/dist/utils/validation.d.ts.map +1 -0
  205. package/dist/utils/validation.js +49 -0
  206. package/dist/utils/validation.js.map +1 -0
  207. package/package.json +72 -0
  208. package/templates/.tiltignore.hbs +73 -0
  209. package/templates/TILT_RESOURCE_DEFAULTS.star.hbs +221 -0
  210. package/templates/TILT_TECH_STACK.star.hbs +150 -0
  211. package/templates/Tiltfile.hbs +295 -0
  212. package/templates/spec.master.hbs +186 -0
@@ -0,0 +1,73 @@
1
+ # =============================================================================
2
+ # 🚫 TDK CLI - TILT IGNORE FILE
3
+ # =============================================================================
4
+ # SYSTEM-GENERATED BY TDK CLI - DO NOT EDIT
5
+ # Source: .tdk/project.json
6
+ # Generated: {{timestamp}}
7
+ # Run 'tdk project' to regenerate
8
+ # =============================================================================
9
+ #
10
+ # This file tells Tilt which directories to ignore during file watching.
11
+ # Prevents fsnotify buffer overflow and reduces unnecessary rebuilds.
12
+ #
13
+ # =============================================================================
14
+
15
+ # Dependency directories
16
+ **/node_modules
17
+
18
+ # Build outputs
19
+ **/dist
20
+ **/build
21
+ **/out
22
+ **/.output
23
+
24
+ # Version control
25
+ **/.git
26
+
27
+ # Generated files
28
+ **/.prisma
29
+ **/.turbo
30
+ **/coverage
31
+ **/tmp
32
+ **/temp
33
+
34
+ # IDE files
35
+ **/.idea
36
+ **/.vscode
37
+ **/*.swp
38
+ **/*.swo
39
+
40
+ # OS files
41
+ **/.DS_Store
42
+ **/Thumbs.db
43
+
44
+ # Docker volumes and data
45
+ **/postgres-data
46
+ **/redis-data
47
+ **/verdaccio-storage
48
+ **/verdaccio-conf
49
+ **/verdaccio-plugins
50
+
51
+ # TDK generated outputs (avoid watching generated files)
52
+ **/.tdk/.tdk-out
53
+ **/.autogenerated/**
54
+ **/.autogenerated/*.autogenerated
55
+ **/.autogenerated/*.autogenerated.json
56
+ **/.autogenerated/*.autogenerated.yml
57
+ **/.autogenerated/*.autogenerated.toml
58
+
59
+ # Logs
60
+ **/*.log
61
+ **/logs
62
+
63
+ # Test outputs
64
+ **/test-results
65
+ **/playwright-report
66
+ **/.nyc_output
67
+
68
+ # Cache directories
69
+ **/.cache
70
+ **/.npm
71
+ **/.bun
72
+ **/bun.lockb
73
+ docker
@@ -0,0 +1,221 @@
1
+ #!/usr/bin/env starlark
2
+ # -*- coding: utf-8 -*-
3
+ # =============================================================================
4
+ # 🔧 TILT SERVICE DEFAULTS MASTER CONFIG
5
+ # =============================================================================
6
+ # SYSTEM-GENERATED BY TDK CLI - DO NOT EDIT
7
+ # Source: TDK Platform Standards v{{version}}
8
+ # Output: .tdk/.tdk-out/
9
+ # Generated: {{timestamp}}
10
+ # Run 'tdk project' to update
11
+ # =============================================================================
12
+
13
+ # Port Configuration
14
+ BASE_PORT_FRONTEND = {{ports.frontend.base}}
15
+ BASE_PORT_BACKEND = {{ports.backend.base}}
16
+ BASE_PORT_HEALTH = {{ports.health.base}}
17
+
18
+ # Port ranges
19
+ PORT_RANGE_FRONTEND_START = {{ports.frontend.start}}
20
+ PORT_RANGE_FRONTEND_END = {{ports.frontend.end}}
21
+ PORT_RANGE_BACKEND_START = {{ports.backend.start}}
22
+ PORT_RANGE_BACKEND_END = {{ports.backend.end}}
23
+ PORT_RANGE_HEALTH_START = {{ports.health.start}}
24
+ PORT_RANGE_HEALTH_END = {{ports.health.end}}
25
+
26
+ # Service Naming Patterns (required by TDK engine)
27
+ NAMING_PATTERNS = {
28
+ "backend_suffix": "{{naming.backend}}",
29
+ "frontend_suffix": "{{naming.frontend}}",
30
+ "migrator_suffix": "{{naming.migrator}}",
31
+ "library_suffix": "{{naming.library}}",
32
+ "sdk_suffix": "{{naming.sdk}}",
33
+ "worker_suffix": "{{naming.worker}}",
34
+ "valid_separators": {{starlarkArray naming.validSeparators}},
35
+ "max_length": {{naming.maxLength}},
36
+ "min_length": {{naming.minLength}},
37
+ }
38
+
39
+ # Traefik Configuration (required by TDK engine)
40
+ TRAEFIK_CONFIG = {
41
+ "entrypoint": "{{traefik.entrypoint}}",
42
+ "network": "{{traefik.network}}",
43
+ "default_host": "{{traefik.defaultHost}}",
44
+ "default_port": {{traefik.defaultPort}},
45
+ "tls_enabled": {{starlark traefik.tlsEnabled}},
46
+ "entrypoints": {{starlarkArray traefik.entrypoints}},
47
+ "middlewares": {{starlarkArray traefik.middlewares}},
48
+ "tls": {"enabled": {{starlark traefik.tlsEnabled}} },
49
+ "healthcheck_path": "{{traefik.healthcheckPath}}",
50
+ "healthcheck_interval": "{{traefik.healthcheckInterval}}",
51
+ "healthcheck_timeout": "{{traefik.healthcheckTimeout}}",
52
+ "frontend_priority_base": {{traefik.frontendPriorityBase}},
53
+ }
54
+
55
+ # Health Check Configuration
56
+ HEALTH_CHECK_PATH = "{{health.path}}"
57
+ HEALTH_CHECK_LIVE = "{{health.live}}"
58
+ HEALTH_CHECK_READY = "{{health.ready}}"
59
+ HEALTH_CHECK_TIMEOUT = {{health.timeout}}
60
+
61
+ # File watch ignore patterns (to prevent fsnotify buffer overflow)
62
+ def get_filewatch_ignore_patterns(resource_path="."):
63
+ """
64
+ Returns list of file patterns to ignore for Tilt filewatch.
65
+
66
+ Args:
67
+ resource_path: Base path of the service
68
+
69
+ Returns:
70
+ List of patterns to ignore
71
+ """
72
+ ignores = [
73
+ {{#each filewatchIgnores}}
74
+ resource_path + "/{{this}}",
75
+ {{/each}}
76
+ ]
77
+ return ignores
78
+
79
+ def get_port_config():
80
+ """Returns the complete port allocation strategy."""
81
+ return {
82
+ "frontend": {
83
+ "base": BASE_PORT_FRONTEND,
84
+ "range_start": PORT_RANGE_FRONTEND_START,
85
+ "range_end": PORT_RANGE_FRONTEND_END,
86
+ },
87
+ "backend": {
88
+ "base": BASE_PORT_BACKEND,
89
+ "range_start": PORT_RANGE_BACKEND_START,
90
+ "range_end": PORT_RANGE_BACKEND_END,
91
+ },
92
+ "health": {
93
+ "base": BASE_PORT_HEALTH,
94
+ "range_start": PORT_RANGE_HEALTH_START,
95
+ "range_end": PORT_RANGE_HEALTH_END,
96
+ },
97
+ }
98
+
99
+ def get_resource_port(resource_type, stack_index=0, resource_index=0):
100
+ """
101
+ Calculate service port based on type and indices.
102
+
103
+ Args:
104
+ resource_type: "frontend" or "backend"
105
+ stack_index: Index of the stack (for port allocation)
106
+ resource_index: Index of the service within stack
107
+
108
+ Returns:
109
+ Port number
110
+ """
111
+ if resource_type == "frontend":
112
+ base = BASE_PORT_FRONTEND
113
+ elif resource_type == "backend":
114
+ base = BASE_PORT_BACKEND
115
+ else:
116
+ fail("Unknown service type: {}".format(resource_type))
117
+
118
+ # Allocate ports: base + (stack_index * 100) + resource_index
119
+ return base + (stack_index * 100) + resource_index
120
+
121
+ def get_health_check_config():
122
+ """Returns health check endpoint configuration."""
123
+ return {
124
+ "path": HEALTH_CHECK_PATH,
125
+ "live": HEALTH_CHECK_LIVE,
126
+ "ready": HEALTH_CHECK_READY,
127
+ "timeout": HEALTH_CHECK_TIMEOUT,
128
+ }
129
+
130
+ def get_build_config():
131
+ """Returns Docker build configuration."""
132
+ return {
133
+ "dockerfile": "{{docker.dockerfile}}",
134
+ "context": "{{docker.context}}",
135
+ {{#if docker.platform}}"platform": "{{docker.platform}}",{{/if}}
136
+ "cache_from": [],
137
+ }
138
+
139
+ def get_runtime_config():
140
+ """Returns runtime command configuration."""
141
+ return {
142
+ "backend": {
143
+ "command": "{{runtime.backend.command}}",
144
+ "args": {{starlarkArray runtime.backend.args}},
145
+ "env": {{starlark runtime.backend.env}},
146
+ },
147
+ "frontend": {
148
+ "command": "{{runtime.frontend.command}}",
149
+ "args": {{starlarkArray runtime.frontend.args}},
150
+ "env": {{starlark runtime.frontend.env}},
151
+ },
152
+ }
153
+
154
+ def get_resource_defaults():
155
+ """Returns complete service defaults."""
156
+ return {
157
+ "port": get_port_config(),
158
+ "health": get_health_check_config(),
159
+ "build": get_build_config(),
160
+ "runtime": get_runtime_config(),
161
+ }
162
+
163
+ def validate_resource_defaults(config):
164
+ """
165
+ Validates service configuration against defaults.
166
+
167
+ Args:
168
+ config: Service configuration dict
169
+
170
+ Returns:
171
+ Dict with validation results
172
+ """
173
+ warnings = []
174
+ errors = []
175
+
176
+ # Validate port allocation
177
+ if "port" in config:
178
+ port = config["port"]
179
+ if port < 1024:
180
+ errors.append("Port {} is in reserved range (< 1024)".format(port))
181
+ elif port > 65535:
182
+ errors.append("Port {} exceeds maximum (65535)".format(port))
183
+
184
+ # Validate health check path
185
+ if "healthCheckPath" in config:
186
+ path = config["healthCheckPath"]
187
+ if not path.startswith("/"):
188
+ errors.append("Health check path must start with /: {}".format(path))
189
+
190
+ return {
191
+ "valid": len(errors) == 0,
192
+ "errors": errors,
193
+ "warnings": warnings,
194
+ }
195
+
196
+ # Export public API
197
+ __all__ = [
198
+ "get_port_config",
199
+ "get_resource_port",
200
+ "get_health_check_config",
201
+ "get_filewatch_ignore_patterns",
202
+ "get_build_config",
203
+ "get_runtime_config",
204
+ "get_resource_defaults",
205
+ "validate_resource_defaults",
206
+ "BASE_PORT_FRONTEND",
207
+ "BASE_PORT_BACKEND",
208
+ "BASE_PORT_HEALTH",
209
+ "PORT_RANGE_FRONTEND_START",
210
+ "PORT_RANGE_FRONTEND_END",
211
+ "PORT_RANGE_BACKEND_START",
212
+ "PORT_RANGE_BACKEND_END",
213
+ "PORT_RANGE_HEALTH_START",
214
+ "PORT_RANGE_HEALTH_END",
215
+ "HEALTH_CHECK_PATH",
216
+ "HEALTH_CHECK_LIVE",
217
+ "HEALTH_CHECK_READY",
218
+ "HEALTH_CHECK_TIMEOUT",
219
+ "NAMING_PATTERNS",
220
+ "TRAEFIK_CONFIG",
221
+ ]
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env starlark
2
+ # -*- coding: utf-8 -*-
3
+ # =============================================================================
4
+ # 🏗️ TILT TECH STACK MASTER CONFIG
5
+ # =============================================================================
6
+ # SYSTEM-GENERATED BY TDK CLI - DO NOT EDIT
7
+ # Source: TDK Platform Standards v{{version}}
8
+ # Output: .tdk/.tdk-out/
9
+ # Generated: {{timestamp}}
10
+ # Run 'tdk project' to update
11
+ # =============================================================================
12
+
13
+ def get_tech_stack():
14
+ """Returns the complete tech stack definition."""
15
+ return {
16
+ "bundler": "{{tech.bundler}}",
17
+ "runtime": "{{tech.runtime}}",
18
+ "language": "{{tech.language}}",
19
+ "orm": "{{tech.orm}}",
20
+ "messaging": "{{tech.messaging}}",
21
+ "linting": "{{tech.linting}}",
22
+ "testing": "{{tech.testing}}",
23
+ "web_framework": "{{tech.framework}}",
24
+ }
25
+
26
+ # Constants for direct import
27
+ BUNDLER = "{{tech.bundler}}"
28
+ RUNTIME = "{{tech.runtime}}"
29
+ ORM = "{{tech.orm}}"
30
+ MESSAGING = "{{tech.messaging}}"
31
+ LINTING = "{{tech.linting}}"
32
+ TESTING = "{{tech.testing}}"
33
+ WEB_FRAMEWORK = "{{tech.framework}}"
34
+ LANGUAGE = "{{tech.language}}"
35
+
36
+ TECH_STACK = get_tech_stack()
37
+
38
+ def validate_tech_stack(config, strict=False):
39
+ """
40
+ Validates a configuration against the platform tech stack.
41
+
42
+ Args:
43
+ config: Dict with tech stack choices to validate
44
+ strict: If True, fails on any non-compliance. If False, warns.
45
+
46
+ Returns:
47
+ Dict with validation results: {"valid": bool, "errors": [], "warnings": []}
48
+ """
49
+ errors = []
50
+ warnings = []
51
+
52
+ # Check for override reason
53
+ has_override = "_override_reason" in config and config["_override_reason"]
54
+
55
+ # Strict validations (must match platform standard)
56
+ strict_validations = {
57
+ "bundler": "{{tech.bundler}}",
58
+ "runtime": "{{tech.runtime}}",
59
+ "orm": "{{tech.orm}}",
60
+ "messaging": "{{tech.messaging}}",
61
+ }
62
+
63
+ for key, standard in strict_validations.items():
64
+ if key in config:
65
+ value = config[key]
66
+ if value.lower() != standard.lower():
67
+ if has_override:
68
+ warnings.append("Override active: {}='{}' (Reason: {})".format(
69
+ key, value, config["_override_reason"]
70
+ ))
71
+ elif strict:
72
+ errors.append(
73
+ "❌ Tech Stack Error: {}: '{}' is not supported. " +
74
+ "Platform standard is '{}'. Use _override_reason to document exceptions.".format(
75
+ key, value, standard
76
+ )
77
+ )
78
+ else:
79
+ warnings.append(
80
+ "⚠️ Tech Stack Warning: {}: '{}' is not standard. " +
81
+ "Platform standard is '{}'.".format(key, value, standard)
82
+ )
83
+
84
+ # Optional validations (warnings if missing or different)
85
+ optional_validations = {
86
+ "linting": "{{tech.linting}}",
87
+ "testing": "{{tech.testing}}",
88
+ }
89
+
90
+ for key, standard in optional_validations.items():
91
+ if key in config:
92
+ value = config[key]
93
+ if value.lower() != standard.lower():
94
+ if has_override:
95
+ warnings.append("Override active: {}='{}' (Reason: {})".format(
96
+ key, value, config["_override_reason"]
97
+ ))
98
+ else:
99
+ warnings.append(
100
+ "⚠️ Tech Stack Warning: {}: '{}' differs from standard '{}'.".format(
101
+ key, value, standard
102
+ )
103
+ )
104
+
105
+ return {
106
+ "valid": len(errors) == 0,
107
+ "errors": errors,
108
+ "warnings": warnings,
109
+ }
110
+
111
+ def assert_tech_stack(config, strict=False):
112
+ """
113
+ Validates tech stack and fails fast on errors.
114
+
115
+ Args:
116
+ config: Dict with tech stack choices to validate
117
+ strict: If True, fails on any non-compliance
118
+
119
+ Raises:
120
+ Exception: If validation fails with errors
121
+ """
122
+ result = validate_tech_stack(config, strict)
123
+
124
+ # Print warnings
125
+ for warning in result["warnings"]:
126
+ print(warning)
127
+
128
+ # Fail on errors
129
+ if not result["valid"]:
130
+ for error in result["errors"]:
131
+ print(error)
132
+ fail("Tech stack validation failed. See errors above.")
133
+
134
+ return result
135
+
136
+ # Export public API
137
+ __all__ = [
138
+ "get_tech_stack",
139
+ "validate_tech_stack",
140
+ "assert_tech_stack",
141
+ "BUNDLER",
142
+ "RUNTIME",
143
+ "ORM",
144
+ "MESSAGING",
145
+ "LINTING",
146
+ "TESTING",
147
+ "WEB_FRAMEWORK",
148
+ "LANGUAGE",
149
+ "TECH_STACK",
150
+ ]