create-win-project 1.3.0 → 2.0.0

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 (289) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +58 -160
  3. package/checks/check-compatibility.js +95 -0
  4. package/{scripts/verify-generated.mjs → checks/check-generated-project.js} +28 -4
  5. package/{scripts/validate-content.mjs → checks/check-library.js} +17 -7
  6. package/checks/check-package.js +15 -0
  7. package/checks/classify-changes.js +29 -0
  8. package/checks/run-compatibility-shard.js +21 -0
  9. package/docs/README.md +20 -0
  10. package/docs/capabilities.md +13 -0
  11. package/docs/compatibility.md +13 -0
  12. package/docs/generated-project.md +12 -0
  13. package/docs/getting-started.md +26 -0
  14. package/docs/maintainers/architecture.md +161 -0
  15. package/docs/maintainers/ci-strategy.md +46 -0
  16. package/docs/{CONTENT_MODEL.md → maintainers/content-model.md} +3 -3
  17. package/docs/maintainers/contributing.md +154 -0
  18. package/docs/{DEPENDENCY_MAINTENANCE.md → maintainers/dependencies.md} +1 -1
  19. package/docs/migration-v2.md +13 -0
  20. package/docs/production-contract.md +24 -0
  21. package/index.js +2 -429
  22. package/{playbooks → library}/INDEX.md +5 -5
  23. package/library/compatibility-impact.json +14 -0
  24. package/{playbooks/capabilities/ci/github-actions.manifest.json → library/development-tools/ci/definition.json} +1 -0
  25. package/library/development-tools/devops/makefile/commands.md +11 -0
  26. package/library/development-tools/devops/makefile/definition.json +11 -0
  27. package/library/development-tools/devops/makefile/docker.md +9 -0
  28. package/library/development-tools/devops/makefile/validation.md +5 -0
  29. package/{playbooks/devops/pr-template.manifest.json → library/development-tools/devops/pr-template/definition.json} +1 -0
  30. package/library/features/sqlalchemy-alembic.md +17 -0
  31. package/library/optional-features/concerns/zod/errors.md +5 -0
  32. package/library/optional-features/concerns/zod/testing.md +5 -0
  33. package/library/optional-features/concerns/zod/validation.md +21 -0
  34. package/library/optional-features/styling/css-modules/definition.json +12 -0
  35. package/library/optional-features/styling/css-modules/responsive.md +5 -0
  36. package/library/optional-features/styling/css-modules/theme.md +7 -0
  37. package/{playbooks/platform/mobile.manifest.json → library/platforms/mobile/definition.json} +1 -0
  38. package/{playbooks/platform/web.manifest.json → library/platforms/web/definition.json} +1 -0
  39. package/{playbooks/stack/react-native.manifest.json → library/stacks/expo/definition.json} +2 -2
  40. package/library/stacks/fastapi/architecture.md +40 -0
  41. package/library/stacks/fastapi/definition.json +39 -0
  42. package/library/stacks/fastapi/runtime.md +25 -0
  43. package/library/stacks/fastapi/security.md +26 -0
  44. package/library/stacks/fastapi/structure.md +27 -0
  45. package/library/stacks/fastapi/testing.md +23 -0
  46. package/{playbooks/stack/nextjs.manifest.json → library/stacks/nextjs/definition.json} +2 -2
  47. package/{playbooks/stack/no-frontend.manifest.json → library/stacks/no-frontend/definition.json} +1 -1
  48. package/{playbooks/stack/react-vite.manifest.json → library/stacks/react-vite/definition.json} +2 -2
  49. package/{compatibility/profiles.json → library/tested-versions.json} +46 -2
  50. package/{playbooks/universal/accessibility.manifest.json → library/universal/accessibility/definition.json} +1 -1
  51. package/library/universal/coding-rules/definition.json +13 -0
  52. package/library/universal/coding-rules/hygiene.md +9 -0
  53. package/library/universal/coding-rules/naming.md +17 -0
  54. package/{playbooks/universal/error-handling.manifest.json → library/universal/error-handling/definition.json} +1 -0
  55. package/library/universal/git-conventions/branches.md +5 -0
  56. package/library/universal/git-conventions/commits.md +7 -0
  57. package/library/universal/git-conventions/definition.json +13 -0
  58. package/library/universal/git-conventions/workflow.md +5 -0
  59. package/{playbooks/universal/observability.manifest.json → library/universal/observability/definition.json} +1 -0
  60. package/{playbooks/universal/security.manifest.json → library/universal/security/definition.json} +1 -0
  61. package/library/universal/typescript/boundaries.md +13 -0
  62. package/library/universal/typescript/definition.json +12 -0
  63. package/library/universal/typescript/errors.md +5 -0
  64. package/library/universal/typescript/patterns.md +7 -0
  65. package/package.json +14 -15
  66. package/public/logo.svg +19 -0
  67. package/src/cli/arguments.js +63 -0
  68. package/src/cli/display.js +220 -0
  69. package/src/cli/main.js +203 -0
  70. package/src/cli/navigation.js +156 -0
  71. package/src/cli/questions.js +188 -0
  72. package/src/cli/system-check.js +158 -0
  73. package/src/engine/create-project.js +10 -0
  74. package/src/engine/install-dependencies.js +13 -0
  75. package/{lib/catalog.js → src/engine/load-library.js} +8 -8
  76. package/{lib/files.js → src/engine/project-files.js} +10 -1
  77. package/{lib/playbooks.js → src/engine/project-guidance.js} +26 -3
  78. package/{lib/application-shapes.js → src/engine/project-shapes.js} +4 -4
  79. package/{lib/template.js → src/engine/render-templates.js} +11 -0
  80. package/{lib/compatibility.js → src/engine/tested-versions.js} +21 -2
  81. package/src/engine/upgrade-report.js +20 -0
  82. package/src/engine/write-files.js +34 -0
  83. package/{lib/stacks/registry.js → src/stacks/available-stacks.js} +25 -1
  84. package/src/stacks/backends/README.md +5 -0
  85. package/src/stacks/backends/fastapi/ci.js +3 -0
  86. package/src/stacks/backends/fastapi/create-files.js +874 -0
  87. package/src/stacks/backends/fastapi/docker.js +75 -0
  88. package/src/stacks/backends/fastapi/environment.js +3 -0
  89. package/src/stacks/backends/fastapi/index.js +32 -0
  90. package/{lib/stacks → src/stacks/backends}/laravel/architecture.js +1 -0
  91. package/{lib/stacks → src/stacks/backends}/laravel/auth/oidc.js +1 -0
  92. package/{lib/stacks → src/stacks/backends}/laravel/auth/public.js +1 -0
  93. package/{lib/stacks → src/stacks/backends}/laravel/auth/sanctum.js +1 -0
  94. package/{lib/stacks → src/stacks/backends}/laravel/auth/session.js +1 -0
  95. package/src/stacks/backends/laravel/ci.js +3 -0
  96. package/{lib/stacks → src/stacks/backends}/laravel/composer.js +1 -1
  97. package/{lib/stacks/laravel/generate.js → src/stacks/backends/laravel/create-files.js} +1 -0
  98. package/src/stacks/backends/laravel/docker.js +14 -0
  99. package/src/stacks/backends/laravel/environment.js +5 -0
  100. package/{lib/stacks → src/stacks/backends}/laravel/index.js +11 -3
  101. package/{lib/stacks → src/stacks/backends}/laravel/ui/blade.js +1 -0
  102. package/{lib/stacks → src/stacks/backends}/laravel/ui/index.js +1 -0
  103. package/{lib/stacks → src/stacks/backends}/laravel/ui/inertia-react.js +4 -2
  104. package/{lib/stacks → src/stacks/backends}/laravel/ui/livewire.js +1 -0
  105. package/{lib/stacks → src/stacks/backends}/laravel/ui/shared.js +1 -0
  106. package/src/stacks/backends/none/index.js +23 -0
  107. package/src/stacks/backends/postgres/ci.js +3 -0
  108. package/src/stacks/backends/postgres/create-files.js +21 -0
  109. package/src/stacks/backends/postgres/docker.js +3 -0
  110. package/src/stacks/backends/postgres/environment.js +3 -0
  111. package/src/stacks/backends/postgres/index.js +30 -0
  112. package/src/stacks/backends/springboot/ci.js +3 -0
  113. package/src/stacks/backends/springboot/create-files.js +91 -0
  114. package/src/stacks/backends/springboot/docker.js +3 -0
  115. package/src/stacks/backends/springboot/environment.js +3 -0
  116. package/src/stacks/backends/springboot/index.js +31 -0
  117. package/src/stacks/backends/supabase/ci.js +3 -0
  118. package/src/stacks/backends/supabase/create-files.js +52 -0
  119. package/src/stacks/backends/supabase/docker.js +3 -0
  120. package/src/stacks/backends/supabase/environment.js +3 -0
  121. package/src/stacks/backends/supabase/index.js +31 -0
  122. package/src/stacks/backends/supabase/native.js +14 -0
  123. package/src/stacks/compose-files.js +259 -0
  124. package/{lib/generator.js → src/stacks/create-project.js} +206 -57
  125. package/src/stacks/frontends/README.md +4 -0
  126. package/src/stacks/frontends/nextjs/ci.js +3 -0
  127. package/src/stacks/frontends/nextjs/create-files.js +46 -0
  128. package/src/stacks/frontends/nextjs/dependencies.js +5 -0
  129. package/src/stacks/frontends/nextjs/docker.js +3 -0
  130. package/src/stacks/frontends/nextjs/environment.js +7 -0
  131. package/src/stacks/frontends/nextjs/index.js +35 -0
  132. package/src/stacks/frontends/react-native/ci.js +3 -0
  133. package/src/stacks/frontends/react-native/create-files.js +28 -0
  134. package/src/stacks/frontends/react-native/dependencies.js +5 -0
  135. package/src/stacks/frontends/react-native/docker.js +5 -0
  136. package/src/stacks/frontends/react-native/environment.js +7 -0
  137. package/src/stacks/frontends/react-native/index.js +30 -0
  138. package/src/stacks/frontends/react-vite/ci.js +3 -0
  139. package/src/stacks/frontends/react-vite/create-files.js +27 -0
  140. package/src/stacks/frontends/react-vite/dependencies.js +5 -0
  141. package/src/stacks/frontends/react-vite/docker.js +3 -0
  142. package/src/stacks/frontends/react-vite/environment.js +8 -0
  143. package/src/stacks/frontends/react-vite/index.js +32 -0
  144. package/src/stacks/shared/capability-packs.js +31 -0
  145. package/{lib → src}/stacks/shared/contributions.js +1 -1
  146. package/src/stacks/shared/environment.js +38 -0
  147. package/src/stacks/shared/javascript-package.js +117 -0
  148. package/src/stacks/shared/testing-files.js +16 -0
  149. package/templates/ci/fastapi.yml +62 -0
  150. package/templates/docker/compose/postgres.yml +1 -1
  151. package/templates/docker/compose/springboot.yml +3 -3
  152. package/templates/docker/compose/supabase.yml +1 -1
  153. package/templates/docker/compose-prod/fastapi.yml +52 -0
  154. package/templates/docker/compose-prod/springboot.yml +20 -2
  155. package/templates/docker/dockerfile/fastapi.dev.dockerfile +9 -0
  156. package/templates/docker/dockerfile/fastapi.prod.dockerfile +11 -0
  157. package/templates/docker/dockerfile/nextjs.prod.dockerfile +1 -0
  158. package/templates/docker/dockerfile/springboot.prod.dockerfile +4 -1
  159. package/templates/docker/dockerfile/vite.prod.dockerfile +2 -1
  160. package/templates/makefile/fastapi.mk +97 -0
  161. package/docs/ARCHITECTURE.md +0 -118
  162. package/lib/banner.js +0 -45
  163. package/lib/constants.js +0 -3
  164. package/lib/doctor.js +0 -45
  165. package/lib/interview.js +0 -77
  166. package/lib/laravel-scaffold.js +0 -3
  167. package/lib/scaffold.js +0 -467
  168. package/lib/stacks/index.js +0 -8
  169. package/playbooks/concerns/zod.md +0 -174
  170. package/playbooks/devops/makefile.manifest.json +0 -10
  171. package/playbooks/devops/makefile.md +0 -556
  172. package/playbooks/styling/css-modules-extensions.md +0 -267
  173. package/playbooks/styling/css-modules.manifest.json +0 -11
  174. package/playbooks/universal/coding-rules.manifest.json +0 -12
  175. package/playbooks/universal/coding-rules.md +0 -281
  176. package/playbooks/universal/git-conventions.manifest.json +0 -10
  177. package/playbooks/universal/git-conventions.md +0 -186
  178. package/playbooks/universal/typescript.manifest.json +0 -11
  179. package/playbooks/universal/typescript.md +0 -272
  180. package/scripts/compatibility-matrix.mjs +0 -48
  181. /package/{playbooks/capabilities → library/development-tools}/ci/github-actions.md +0 -0
  182. /package/{playbooks/devops → library/development-tools/devops/pr-template}/pr-template.md +0 -0
  183. /package/{playbooks/capabilities/docker/docker.manifest.json → library/development-tools/docker/definition.json} +0 -0
  184. /package/{playbooks/capabilities → library/development-tools}/docker/overview.md +0 -0
  185. /package/{playbooks/capabilities → library/features}/auth/oidc-resource-server.md +0 -0
  186. /package/{playbooks/capabilities → library/features}/auth/spring-session.md +0 -0
  187. /package/{playbooks/capabilities/flyway/flyway.manifest.json → library/features/flyway/definition.json} +0 -0
  188. /package/{playbooks/capabilities → library/features}/flyway/environments.md +0 -0
  189. /package/{playbooks/capabilities → library/features}/flyway/migrations.md +0 -0
  190. /package/{playbooks/capabilities → library/features}/flyway/testing.md +0 -0
  191. /package/{playbooks/capabilities → library/features}/laravel/database.md +0 -0
  192. /package/{playbooks/capabilities → library/features}/laravel/migrations.md +0 -0
  193. /package/{playbooks/capabilities → library/features}/laravel/observability.md +0 -0
  194. /package/{playbooks/capabilities → library/features}/laravel/oidc-resource-server.md +0 -0
  195. /package/{playbooks/capabilities → library/features}/laravel/queues.md +0 -0
  196. /package/{playbooks/capabilities → library/features}/laravel/sanctum-spa.md +0 -0
  197. /package/{playbooks/capabilities → library/features}/laravel/scheduler.md +0 -0
  198. /package/{playbooks/capabilities → library/features}/laravel/session-auth.md +0 -0
  199. /package/{playbooks/capabilities → library/features}/laravel/storage-uploads.md +0 -0
  200. /package/{playbooks/capabilities → library/features}/postgresql/architecture.md +0 -0
  201. /package/{playbooks/capabilities/postgresql/postgresql.manifest.json → library/features/postgresql/definition.json} +0 -0
  202. /package/{playbooks/capabilities → library/features}/postgresql/migrations.md +0 -0
  203. /package/{playbooks/capabilities → library/features}/postgresql/schema-design.md +0 -0
  204. /package/{playbooks/capabilities → library/features}/postgresql/security.md +0 -0
  205. /package/{playbooks/capabilities → library/features}/postgresql/testing.md +0 -0
  206. /package/{playbooks/capabilities → library/features}/prisma/architecture.md +0 -0
  207. /package/{playbooks/capabilities/prisma/prisma.manifest.json → library/features/prisma/definition.json} +0 -0
  208. /package/{playbooks/capabilities → library/features}/prisma/migrations.md +0 -0
  209. /package/{playbooks/capabilities → library/features}/prisma/runtime.md +0 -0
  210. /package/{playbooks/capabilities → library/features}/prisma/schema.md +0 -0
  211. /package/{playbooks/capabilities → library/features}/prisma/testing.md +0 -0
  212. /package/{playbooks/capabilities → library/features}/supabase/architecture.md +0 -0
  213. /package/{playbooks/capabilities → library/features}/supabase/authentication.md +0 -0
  214. /package/{playbooks/capabilities/supabase/supabase.manifest.json → library/features/supabase/definition.json} +0 -0
  215. /package/{playbooks/capabilities → library/features}/supabase/expo.md +0 -0
  216. /package/{playbooks/capabilities → library/features}/supabase/migrations.md +0 -0
  217. /package/{playbooks/capabilities → library/features}/supabase/nextjs.md +0 -0
  218. /package/{playbooks/capabilities → library/features}/supabase/rls.md +0 -0
  219. /package/{playbooks/capabilities → library/features}/supabase/testing.md +0 -0
  220. /package/{playbooks/capabilities → library/features}/supabase/vite.md +0 -0
  221. /package/{playbooks → library/optional-features}/concerns/axios.md +0 -0
  222. /package/{playbooks → library/optional-features}/concerns/next-safe-action.md +0 -0
  223. /package/{playbooks → library/optional-features}/concerns/next-themes.md +0 -0
  224. /package/{playbooks → library/optional-features}/concerns/nuqs.md +0 -0
  225. /package/{playbooks → library/optional-features}/concerns/t3-env.md +0 -0
  226. /package/{playbooks → library/optional-features}/concerns/tanstack-query.md +0 -0
  227. /package/{playbooks → library/optional-features}/concerns/zustand.md +0 -0
  228. /package/{playbooks/styling/native-styles.manifest.json → library/optional-features/styling/native-styles/definition.json} +0 -0
  229. /package/{playbooks/styling → library/optional-features/styling/native-styles}/native-styles.md +0 -0
  230. /package/{playbooks/styling/tailwind.manifest.json → library/optional-features/styling/tailwind/definition.json} +0 -0
  231. /package/{playbooks/styling → library/optional-features/styling/tailwind}/tailwind-extensions.md +0 -0
  232. /package/{playbooks/platform → library/platforms}/laravel-ui/blade/architecture.md +0 -0
  233. /package/{playbooks/platform → library/platforms}/laravel-ui/blade/runtime.md +0 -0
  234. /package/{playbooks/platform → library/platforms}/laravel-ui/blade/security.md +0 -0
  235. /package/{playbooks/platform → library/platforms}/laravel-ui/blade/structure.md +0 -0
  236. /package/{playbooks/platform → library/platforms}/laravel-ui/blade/testing.md +0 -0
  237. /package/{playbooks/stack/laravel-ui.manifest.json → library/platforms/laravel-ui/definition.json} +0 -0
  238. /package/{playbooks/platform → library/platforms}/laravel-ui/inertia-react/architecture.md +0 -0
  239. /package/{playbooks/platform → library/platforms}/laravel-ui/inertia-react/runtime.md +0 -0
  240. /package/{playbooks/platform → library/platforms}/laravel-ui/inertia-react/security.md +0 -0
  241. /package/{playbooks/platform → library/platforms}/laravel-ui/inertia-react/structure.md +0 -0
  242. /package/{playbooks/platform → library/platforms}/laravel-ui/inertia-react/testing.md +0 -0
  243. /package/{playbooks/platform → library/platforms}/laravel-ui/livewire/architecture.md +0 -0
  244. /package/{playbooks/platform → library/platforms}/laravel-ui/livewire/runtime.md +0 -0
  245. /package/{playbooks/platform → library/platforms}/laravel-ui/livewire/security.md +0 -0
  246. /package/{playbooks/platform → library/platforms}/laravel-ui/livewire/structure.md +0 -0
  247. /package/{playbooks/platform → library/platforms}/laravel-ui/livewire/testing.md +0 -0
  248. /package/{playbooks/platform → library/platforms/mobile}/mobile.md +0 -0
  249. /package/{playbooks/platform → library/platforms/web}/web.md +0 -0
  250. /package/{playbooks/stack → library/stacks}/expo/architecture.md +0 -0
  251. /package/{playbooks/stack → library/stacks}/expo/runtime.md +0 -0
  252. /package/{playbooks/stack → library/stacks}/expo/security.md +0 -0
  253. /package/{playbooks/stack → library/stacks}/expo/structure.md +0 -0
  254. /package/{playbooks/stack → library/stacks}/expo/testing.md +0 -0
  255. /package/{playbooks/stack → library/stacks}/laravel/architecture.md +0 -0
  256. /package/{playbooks/stack/laravel.manifest.json → library/stacks/laravel/definition.json} +0 -0
  257. /package/{playbooks/stack → library/stacks}/laravel/runtime.md +0 -0
  258. /package/{playbooks/stack → library/stacks}/laravel/security.md +0 -0
  259. /package/{playbooks/stack → library/stacks}/laravel/structure.md +0 -0
  260. /package/{playbooks/stack → library/stacks}/laravel/testing.md +0 -0
  261. /package/{playbooks/stack → library/stacks}/nextjs/architecture.md +0 -0
  262. /package/{playbooks/stack → library/stacks}/nextjs/runtime.md +0 -0
  263. /package/{playbooks/stack → library/stacks}/nextjs/security.md +0 -0
  264. /package/{playbooks/stack → library/stacks}/nextjs/structure.md +0 -0
  265. /package/{playbooks/stack → library/stacks}/nextjs/testing.md +0 -0
  266. /package/{playbooks/stack/none.manifest.json → library/stacks/none/definition.json} +0 -0
  267. /package/{playbooks/stack → library/stacks}/react-vite/architecture.md +0 -0
  268. /package/{playbooks/stack → library/stacks}/react-vite/runtime.md +0 -0
  269. /package/{playbooks/stack → library/stacks}/react-vite/security.md +0 -0
  270. /package/{playbooks/stack → library/stacks}/react-vite/structure.md +0 -0
  271. /package/{playbooks/stack → library/stacks}/react-vite/testing.md +0 -0
  272. /package/{playbooks/stack → library/stacks}/springboot/architecture.md +0 -0
  273. /package/{playbooks/stack/springboot.manifest.json → library/stacks/springboot/definition.json} +0 -0
  274. /package/{playbooks/stack → library/stacks}/springboot/runtime.md +0 -0
  275. /package/{playbooks/stack → library/stacks}/springboot/security.md +0 -0
  276. /package/{playbooks/stack → library/stacks}/springboot/structure.md +0 -0
  277. /package/{playbooks/stack → library/stacks}/springboot/testing.md +0 -0
  278. /package/{playbooks/universal → library/universal/accessibility}/accessibility.md +0 -0
  279. /package/{playbooks/universal → library/universal/error-handling}/error-handling.md +0 -0
  280. /package/{playbooks/universal → library/universal/observability}/observability.md +0 -0
  281. /package/{playbooks/universal → library/universal/security}/security.md +0 -0
  282. /package/{lib → src/engine}/project-location.js +0 -0
  283. /package/{lib → src}/stacks/context.js +0 -0
  284. /package/{lib/stacks/contract.js → src/stacks/rules.js} +0 -0
  285. /package/{ci → templates/ci}/expo.yml +0 -0
  286. /package/{ci → templates/ci}/laravel.yml +0 -0
  287. /package/{ci → templates/ci}/nextjs.yml +0 -0
  288. /package/{ci → templates/ci}/springboot.yml +0 -0
  289. /package/{ci → templates/ci}/vite.yml +0 -0
@@ -0,0 +1,97 @@
1
+ # =============================================================================
2
+ # Makefile — {{PROJECT_NAME}}
3
+ # =============================================================================
4
+
5
+ # Variables
6
+ COMPOSE := docker compose
7
+ BACKEND := $(COMPOSE) exec backend
8
+ DB := $(COMPOSE) exec db
9
+ WORKDIR := $(PWD)
10
+
11
+ # =============================================================================
12
+ # Default
13
+ # =============================================================================
14
+
15
+ .DEFAULT_GOAL := help
16
+
17
+ .PHONY: help
18
+ help: ## Show all available commands
19
+ @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) \
20
+ | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
21
+
22
+ # =============================================================================
23
+ # Project Lifecycle
24
+ # =============================================================================
25
+
26
+ .PHONY: dev up down restart logs logs-back clean
27
+
28
+ dev: ## Start all containers and follow logs
29
+ $(COMPOSE) up --build
30
+
31
+ up: ## Start all containers in background
32
+ $(COMPOSE) up -d --build
33
+
34
+ down: ## Stop and remove all containers
35
+ $(COMPOSE) down
36
+
37
+ restart: down up ## Stop then start all containers
38
+
39
+ logs: ## Follow logs from all containers
40
+ $(COMPOSE) logs -f
41
+
42
+ logs-back: ## Follow backend logs only
43
+ $(COMPOSE) logs -f backend
44
+
45
+ clean: ## Remove containers, volumes, orphans (full reset)
46
+ $(COMPOSE) down -v --remove-orphans
47
+
48
+ # =============================================================================
49
+ # Database
50
+ # =============================================================================
51
+
52
+ .PHONY: migrate db-shell
53
+
54
+ migrate: ## Run pending Alembic migrations
55
+ $(BACKEND) uv run alembic upgrade head
56
+
57
+ db-shell: ## Open psql shell inside DB container
58
+ $(DB) psql -U $${POSTGRES_USER} -d $${POSTGRES_DB}
59
+
60
+ # =============================================================================
61
+ # Shells
62
+ # =============================================================================
63
+
64
+ .PHONY: shell-back
65
+
66
+ shell-back: ## Open shell inside backend container
67
+ $(BACKEND) sh
68
+
69
+ # =============================================================================
70
+ # Quality
71
+ # =============================================================================
72
+
73
+ .PHONY: lint test test-back
74
+
75
+ lint: ## Run Ruff check and format check (backend)
76
+ $(BACKEND) uv run ruff check .
77
+ $(BACKEND) uv run ruff format --check .
78
+
79
+ test: test-back ## Run all tests
80
+
81
+ test-back: ## Run pytest (backend)
82
+ $(BACKEND) uv run pytest
83
+
84
+ # =============================================================================
85
+ # Production
86
+ # =============================================================================
87
+
88
+ .PHONY: build prod-up prod-down
89
+
90
+ build: ## Build production Docker images
91
+ $(COMPOSE) -f docker-compose.prod.yml build
92
+
93
+ prod-up: ## Start production stack
94
+ $(COMPOSE) -f docker-compose.prod.yml up -d --build
95
+
96
+ prod-down: ## Stop production stack
97
+ $(COMPOSE) -f docker-compose.prod.yml down
@@ -1,118 +0,0 @@
1
- # Architecture
2
-
3
- `create-win-project` composes a validated project specification into two coordinated outputs:
4
-
5
- 1. a small executable application that establishes the stack's real conventions;
6
- 2. a task-routed documentation layer for humans and coding agents.
7
-
8
- Executable behavior, tests, and framework configuration are the source of truth. Playbooks explain and extend that behavior; they must not contradict it.
9
-
10
- ## Generation pipeline
11
-
12
- ```text
13
- CLI interview
14
-
15
- validated answers
16
-
17
- manifest catalog + compatibility resolver
18
-
19
- resolved stack descriptor
20
- ├── runnable framework files
21
- ├── optional CI / Docker / Makefile files
22
- ├── project context and documentation
23
- └── selected playbooks + RULES.md router
24
-
25
- generated-project contract tests
26
- ```
27
-
28
- ### CLI boundary
29
-
30
- `index.js` owns interaction and presentation. It gathers project identity, frontend, optional backend, styling, one Small/Medium/Large architecture profile, login intent, client audience when relevant, testing depth, and optional operational tooling. Medium is shown first and is the default. It does not contain stack dependency tables.
31
-
32
- `generateProject()` validates the same answers again because it is also an exported programmatic API. A caller cannot bypass destination-name, Java-package, or testing-profile validation by skipping the CLI.
33
-
34
- ### Catalog and resolution
35
-
36
- `lib/catalog.js` loads co-located `*.manifest.json` files and merges selected capabilities into one stack descriptor. `lib/compatibility.js` validates `compatibility/profiles.json` and resolves every package name to an exact version for the selected profile.
37
-
38
- Stack-specific behavior crosses into core orchestration through the contract in `lib/stacks/contract.js`. Every frontend, backend, or data adapter has a stable identity, declares compatible adapters and supported application/authentication/architecture models, and is added to the explicit registry. Registration is deliberate; adapters are never discovered by scanning directories.
39
-
40
- Adapters may contribute data in these areas:
41
-
42
- - questions in a core-defined prompt slot;
43
- - authentication models;
44
- - generated file descriptions;
45
- - environment declarations;
46
- - install steps;
47
- - Docker and CI fragments;
48
- - verification cases.
49
-
50
- Core code owns prompt order, compatibility-profile resolution, atomic writes, process execution, and final composition. An adapter receives a read-only stack context and returns contributions; it cannot write arbitrary paths or install global tools. Adapter definitions do not accept dependency tables or version fields. Exact versions remain exclusively owned by `compatibility/profiles.json`.
51
-
52
- Manifests declare:
53
-
54
- - identity and compatibility (`id`, `kind`, `appliesTo`);
55
- - dependency names and scripts (never dependency versions);
56
- - semantic environment names and which ones are client-visible;
57
- - supported architecture profiles, conditional playbooks, and optional templates;
58
- - constraints shown to the agent;
59
- - concerns and their playbook sections.
60
-
61
- Client environment variables are semantic in manifests (`API_URL`) and receive exactly one framework prefix during resolution (`NEXT_PUBLIC_API_URL`, `VITE_API_URL`, or `EXPO_PUBLIC_API_URL`). Public prefixes always mean the value is shipped to the client.
62
-
63
- ### Runnable scaffold
64
-
65
- `lib/scaffold.js` owns the minimum executable vertical slice:
66
-
67
- - Next.js: route-oriented Small; familiar feature services/actions/queries and owned repositories or remote API clients in Medium; public feature APIs and enforced boundaries in Large.
68
- - React + Vite: thin browser features in Small, feature modules in Medium, and public feature APIs plus boundary checks in Large.
69
- - Expo: screens/data in Small, feature modules in Medium, and boundaries ready for offline sync, background work, and platform adapters in Large.
70
- - Spring Boot: conventional package-by-feature in Small, explicit API/service/repository ownership in Medium, and a verified Spring Modulith modular monolith in Large.
71
-
72
- Authentication is selected during generation. Supabase emits Supabase Auth clients and login examples; website-only Spring uses a secure server-managed session; multi-client Spring emits an OIDC Resource Server and delegates issuance, refresh, and revocation to the identity provider. `Not yet` is fail-closed for Spring and never emits pretend authentication. Existing projects are never told to rerun the generator to add auth.
73
-
74
- This module intentionally generates a small working example. Domain-specific features are added after product context is known; the generator does not invent business entities.
75
-
76
- ### Repository and operational files
77
-
78
- `lib/generator.js` coordinates writes and refuses to merge into a non-empty destination. It adds documentation, selected playbooks, CI, Docker, Makefile, environment examples, and repository conventions around the runnable foundation.
79
-
80
- The first `npm install` creates the lockfile. Generated CI uses `npm ci`, so the lockfile must be committed before CI is enabled. `create-win-project.profile.json` separately records the compatibility profile, architecture profile, and authentication intent/model/audience; after generation, that project owns its own upgrade lifecycle.
81
-
82
- ### Compatibility profile lifecycle
83
-
84
- Exactly one profile is `current` and one is `previous`. The current profile is the default. A profile owns exact npm, Spring Boot, runtime, and container versions; manifests and scaffold code may only request names or capabilities. Promotion copies the candidate into a new dated profile, marks the former current profile previous, and happens only after the generated-project matrix passes. Major changes also require migration notes. See `DEPENDENCY_MAINTENANCE.md`.
85
-
86
- ## Documentation model
87
-
88
- | File | Responsibility |
89
- |------|----------------|
90
- | `AGENTS.md` | Small always-on command, workflow, safety, and definition-of-done contract. |
91
- | `CONTEXT.md` | Product goals, boundaries, decisions, and project-specific facts. |
92
- | `RULES.md` | Generated concern-to-playbook section router. |
93
- | `playbooks/` | Reusable standards, recipes, rationale, and stack guidance. |
94
- | `docs/` | Documentation for the generated product, not generic framework teaching. |
95
-
96
- Manifest section names are checked against Markdown headings. Numbered headings are normalized for matching, and generated contract tests reject unresolved `RULES.md` entries.
97
-
98
- ## Testing strategy
99
-
100
- The generator itself has three verification levels:
101
-
102
- 1. unit tests for catalog composition and template rendering;
103
- 2. generated-output contract tests for required files, environment naming, playbook routing, profile-specific boundaries, auth metadata/code, testing profiles, and overwrite safety;
104
- 3. a current-and-previous matrix across every supported stack combination, all three architecture profiles, and every applicable authentication model. It installs and runs lint, typecheck, tests, builds, Expo compatibility checks/web export, Spring MVC/security/Modulith tests and Maven packaging, Compose validation, and current-profile container builds.
105
-
106
- Canonical Markdown code examples should progressively move into extracted fixtures so examples compile against the versions they teach.
107
-
108
- ## Extension workflow
109
-
110
- When adding a stack or capability:
111
-
112
- 1. Add its manifest, all five stack facets, and any platform/capability routes.
113
- 2. Add the smallest runnable files needed in `lib/scaffold.js` or a focused scaffold module.
114
- 3. Add every supported architecture/authentication combination to the generated-output matrix.
115
- 4. Run install, lint/typecheck, tests, and production build for the new fixture.
116
- 5. Update this architecture document if ownership or the generation pipeline changed.
117
-
118
- Do not advertise a capability solely because a playbook mentions it. A generated capability must have executable configuration and contract coverage.
package/lib/banner.js DELETED
@@ -1,45 +0,0 @@
1
- import chalk from 'chalk'
2
-
3
- const W1N = [
4
- ' ██╗ ██╗ ██╗ ███╗ ██╗',
5
- ' ██║ ██║ ███║ ████╗ ██║',
6
- ' ██║ █╗ ██║ ╚██║ ██╔██╗██║',
7
- ' ██║███╗██║ ██║ ██║╚████║',
8
- ' ╚███╔███╔╝ ██║ ██║ ╚███║',
9
- ' ╚══╝╚══╝ ╚═╝ ╚═╝ ╚══╝',
10
- ]
11
-
12
- const PROJECT = [
13
- ' █▀█ █▀█ █▀█ █ █▀▀ █▀▀ ▀█▀',
14
- ' █▀▀ █▀█ █ █ █ █▀ █ █ ',
15
- ' █ █ █ █▄█ █▄█ █▄▄ █▄▄ █ ',
16
- ]
17
-
18
- function plain() {
19
- return [...W1N, '', ...PROJECT].join('\n')
20
- }
21
-
22
- function colored() {
23
- const w1n = W1N.map((l) => chalk.bold.cyan(l)).join('\n')
24
- const proj = PROJECT.map((l) => chalk.bold.white(l)).join('\n')
25
- return `${w1n}\n${proj}`
26
- }
27
-
28
- export function w1nBanner() {
29
- const noColor = process.env.NO_COLOR !== undefined || process.env.FORCE_COLOR === '0'
30
- const isTTY = process.stdout.isTTY
31
- const width = process.stdout.columns || 80
32
-
33
- // Fallback for narrow terminals or non-TTY (CI/logs): plain single-line wordmark
34
- if (!isTTY || width < 80 || noColor) {
35
- // Keep stacked plain for README consistency, but without colors
36
- if (width < 60) return 'W1N PROJECT'
37
- return plain()
38
- }
39
-
40
- return colored()
41
- }
42
-
43
- export const bannerRaw = plain()
44
- export const W1N_ART = W1N.join('\n')
45
- export const PROJECT_ART = PROJECT.join('\n')
package/lib/constants.js DELETED
@@ -1,3 +0,0 @@
1
- // Deprecated: stack composition now lives in playbooks/*.manifest.json + lib/catalog.js.
2
- // Kept as an empty module so any stray import does not break resolution.
3
- export {}
package/lib/doctor.js DELETED
@@ -1,45 +0,0 @@
1
- import { spawnSync } from 'node:child_process'
2
- import { existsSync } from 'node:fs'
3
- import path from 'node:path'
4
-
5
- function isOnPath(command) {
6
- const suffixes = process.platform === 'win32' ? ['', '.cmd', '.exe', '.bat'] : ['']
7
- return (process.env.PATH || '').split(path.delimiter).some((directory) =>
8
- suffixes.some((suffix) => existsSync(path.join(directory, `${command}${suffix}`)))
9
- )
10
- }
11
-
12
- function probe(command, args = ['--version']) {
13
- const result = spawnSync(command, args, { encoding: 'utf8', shell: false })
14
- const version = `${result.stdout || result.stderr || ''}`.trim().split('\n')[0]
15
- if (!version) return isOnPath(command) ? 'available (version unavailable)' : null
16
- if (result.status !== 0) return null
17
- return version
18
- }
19
-
20
- export function collectDiagnostics(profile) {
21
- const nodeVersion = process.versions.node
22
- const npmVersion = probe('npm')
23
- const dockerVersion = probe('docker')
24
- const composeVersion = dockerVersion ? probe('docker', ['compose', 'version']) : null
25
- const javaVersion = probe('java', ['-version'])
26
- return [
27
- { name: 'Node.js', found: nodeVersion, expected: profile.runtimes.node, required: false },
28
- { name: 'npm', found: npmVersion, required: false },
29
- { name: 'Docker', found: dockerVersion, required: false },
30
- { name: 'Docker Compose', found: composeVersion, required: false },
31
- { name: 'Java', found: javaVersion, expected: profile.runtimes.java, required: false },
32
- ]
33
- }
34
-
35
- export function printDoctor(profile, output = console.log) {
36
- output(`create-win-project doctor (profile ${profile.id})`)
37
- output('Use either the Node/npm lane or the Docker/Compose lane; Java is only needed for host-run Spring projects.')
38
- for (const item of collectDiagnostics(profile)) {
39
- const expectation = item.expected ? ` (tested: ${item.expected})` : ''
40
- output(`${item.found ? '✓' : '○'} ${item.name}: ${item.found || 'not found'}${expectation}`)
41
- }
42
- output('')
43
- output('Node lane: npm ci && npm start')
44
- output('Docker lane: docker compose build && docker compose run --rm app')
45
- }
package/lib/interview.js DELETED
@@ -1,77 +0,0 @@
1
- const BACK = Symbol('back')
2
-
3
- function enabled(question, answers) {
4
- return typeof question.when === 'function' ? question.when(answers) : question.when !== false
5
- }
6
-
7
- async function resolved(value, answers) {
8
- return typeof value === 'function' ? value(answers) : value
9
- }
10
-
11
- function clearFrom(questions, answers, index) {
12
- for (let cursor = index; cursor < questions.length; cursor += 1) {
13
- delete answers[questions[cursor].name]
14
- }
15
- }
16
-
17
- /**
18
- * Runs Inquirer questions one at a time so users can safely revisit earlier answers.
19
- * List/checkbox/confirm prompts expose a visible Back choice; text prompts accept `:back`.
20
- */
21
- export async function promptWithBack(inquirer, questions, initialAnswers = {}) {
22
- const answers = { ...initialAnswers }
23
- const history = []
24
- let index = 0
25
-
26
- while (index < questions.length) {
27
- const source = questions[index]
28
- if (!enabled(source, answers)) { index += 1; continue }
29
-
30
- const canGoBack = history.length > 0
31
- const question = { ...source, when: undefined }
32
- if (answers[source.name] !== undefined && question.default === undefined) {
33
- question.default = answers[source.name]
34
- }
35
- if (question.type === 'input' && canGoBack) {
36
- question.message = `${question.message} (type :back to return)`
37
- } else if (question.type === 'confirm') {
38
- const defaultValue = await resolved(question.default, answers)
39
- question.type = 'list'
40
- question.choices = [
41
- { name: 'Yes', value: true },
42
- { name: 'No', value: false },
43
- ...(canGoBack ? [{ name: '← Back', value: BACK }] : []),
44
- ]
45
- question.default = defaultValue ? 0 : 1
46
- } else if (['list', 'checkbox'].includes(question.type) && canGoBack) {
47
- const choices = await resolved(question.choices, answers)
48
- question.choices = [...choices, new inquirer.Separator(), { name: '← Back', value: BACK }]
49
- }
50
-
51
- if (typeof question.default === 'function') question.default = await question.default(answers)
52
- const result = await inquirer.prompt([question], answers)
53
- const value = result[source.name]
54
- const requestedBack = value === BACK || value === ':back' || (Array.isArray(value) && value.includes(BACK))
55
- if (requestedBack) {
56
- const target = history.pop()
57
- if (target === undefined) continue
58
- clearFrom(questions, answers, target)
59
- index = target
60
- continue
61
- }
62
-
63
- answers[source.name] = value
64
- history.push(index)
65
- index += 1
66
- }
67
-
68
- return answers
69
- }
70
-
71
- export function configurationDecisionChoices() {
72
- return [
73
- { name: 'Create project', value: 'create' },
74
- { name: '← Back and edit', value: 'back' },
75
- { name: 'Cancel', value: 'cancel' },
76
- ]
77
- }
@@ -1,3 +0,0 @@
1
- // Compatibility export for programmatic consumers. Laravel generation now
2
- // lives behind its stack adapter boundary.
3
- export { buildLaravelFiles } from './stacks/laravel/generate.js'