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.
- package/LICENSE +1 -1
- package/README.md +58 -160
- package/checks/check-compatibility.js +95 -0
- package/{scripts/verify-generated.mjs → checks/check-generated-project.js} +28 -4
- package/{scripts/validate-content.mjs → checks/check-library.js} +17 -7
- package/checks/check-package.js +15 -0
- package/checks/classify-changes.js +29 -0
- package/checks/run-compatibility-shard.js +21 -0
- package/docs/README.md +20 -0
- package/docs/capabilities.md +13 -0
- package/docs/compatibility.md +13 -0
- package/docs/generated-project.md +12 -0
- package/docs/getting-started.md +26 -0
- package/docs/maintainers/architecture.md +161 -0
- package/docs/maintainers/ci-strategy.md +46 -0
- package/docs/{CONTENT_MODEL.md → maintainers/content-model.md} +3 -3
- package/docs/maintainers/contributing.md +154 -0
- package/docs/{DEPENDENCY_MAINTENANCE.md → maintainers/dependencies.md} +1 -1
- package/docs/migration-v2.md +13 -0
- package/docs/production-contract.md +24 -0
- package/index.js +2 -429
- package/{playbooks → library}/INDEX.md +5 -5
- package/library/compatibility-impact.json +14 -0
- package/{playbooks/capabilities/ci/github-actions.manifest.json → library/development-tools/ci/definition.json} +1 -0
- package/library/development-tools/devops/makefile/commands.md +11 -0
- package/library/development-tools/devops/makefile/definition.json +11 -0
- package/library/development-tools/devops/makefile/docker.md +9 -0
- package/library/development-tools/devops/makefile/validation.md +5 -0
- package/{playbooks/devops/pr-template.manifest.json → library/development-tools/devops/pr-template/definition.json} +1 -0
- package/library/features/sqlalchemy-alembic.md +17 -0
- package/library/optional-features/concerns/zod/errors.md +5 -0
- package/library/optional-features/concerns/zod/testing.md +5 -0
- package/library/optional-features/concerns/zod/validation.md +21 -0
- package/library/optional-features/styling/css-modules/definition.json +12 -0
- package/library/optional-features/styling/css-modules/responsive.md +5 -0
- package/library/optional-features/styling/css-modules/theme.md +7 -0
- package/{playbooks/platform/mobile.manifest.json → library/platforms/mobile/definition.json} +1 -0
- package/{playbooks/platform/web.manifest.json → library/platforms/web/definition.json} +1 -0
- package/{playbooks/stack/react-native.manifest.json → library/stacks/expo/definition.json} +2 -2
- package/library/stacks/fastapi/architecture.md +40 -0
- package/library/stacks/fastapi/definition.json +39 -0
- package/library/stacks/fastapi/runtime.md +25 -0
- package/library/stacks/fastapi/security.md +26 -0
- package/library/stacks/fastapi/structure.md +27 -0
- package/library/stacks/fastapi/testing.md +23 -0
- package/{playbooks/stack/nextjs.manifest.json → library/stacks/nextjs/definition.json} +2 -2
- package/{playbooks/stack/no-frontend.manifest.json → library/stacks/no-frontend/definition.json} +1 -1
- package/{playbooks/stack/react-vite.manifest.json → library/stacks/react-vite/definition.json} +2 -2
- package/{compatibility/profiles.json → library/tested-versions.json} +46 -2
- package/{playbooks/universal/accessibility.manifest.json → library/universal/accessibility/definition.json} +1 -1
- package/library/universal/coding-rules/definition.json +13 -0
- package/library/universal/coding-rules/hygiene.md +9 -0
- package/library/universal/coding-rules/naming.md +17 -0
- package/{playbooks/universal/error-handling.manifest.json → library/universal/error-handling/definition.json} +1 -0
- package/library/universal/git-conventions/branches.md +5 -0
- package/library/universal/git-conventions/commits.md +7 -0
- package/library/universal/git-conventions/definition.json +13 -0
- package/library/universal/git-conventions/workflow.md +5 -0
- package/{playbooks/universal/observability.manifest.json → library/universal/observability/definition.json} +1 -0
- package/{playbooks/universal/security.manifest.json → library/universal/security/definition.json} +1 -0
- package/library/universal/typescript/boundaries.md +13 -0
- package/library/universal/typescript/definition.json +12 -0
- package/library/universal/typescript/errors.md +5 -0
- package/library/universal/typescript/patterns.md +7 -0
- package/package.json +14 -15
- package/public/logo.svg +19 -0
- package/src/cli/arguments.js +63 -0
- package/src/cli/display.js +220 -0
- package/src/cli/main.js +203 -0
- package/src/cli/navigation.js +156 -0
- package/src/cli/questions.js +188 -0
- package/src/cli/system-check.js +158 -0
- package/src/engine/create-project.js +10 -0
- package/src/engine/install-dependencies.js +13 -0
- package/{lib/catalog.js → src/engine/load-library.js} +8 -8
- package/{lib/files.js → src/engine/project-files.js} +10 -1
- package/{lib/playbooks.js → src/engine/project-guidance.js} +26 -3
- package/{lib/application-shapes.js → src/engine/project-shapes.js} +4 -4
- package/{lib/template.js → src/engine/render-templates.js} +11 -0
- package/{lib/compatibility.js → src/engine/tested-versions.js} +21 -2
- package/src/engine/upgrade-report.js +20 -0
- package/src/engine/write-files.js +34 -0
- package/{lib/stacks/registry.js → src/stacks/available-stacks.js} +25 -1
- package/src/stacks/backends/README.md +5 -0
- package/src/stacks/backends/fastapi/ci.js +3 -0
- package/src/stacks/backends/fastapi/create-files.js +874 -0
- package/src/stacks/backends/fastapi/docker.js +75 -0
- package/src/stacks/backends/fastapi/environment.js +3 -0
- package/src/stacks/backends/fastapi/index.js +32 -0
- package/{lib/stacks → src/stacks/backends}/laravel/architecture.js +1 -0
- package/{lib/stacks → src/stacks/backends}/laravel/auth/oidc.js +1 -0
- package/{lib/stacks → src/stacks/backends}/laravel/auth/public.js +1 -0
- package/{lib/stacks → src/stacks/backends}/laravel/auth/sanctum.js +1 -0
- package/{lib/stacks → src/stacks/backends}/laravel/auth/session.js +1 -0
- package/src/stacks/backends/laravel/ci.js +3 -0
- package/{lib/stacks → src/stacks/backends}/laravel/composer.js +1 -1
- package/{lib/stacks/laravel/generate.js → src/stacks/backends/laravel/create-files.js} +1 -0
- package/src/stacks/backends/laravel/docker.js +14 -0
- package/src/stacks/backends/laravel/environment.js +5 -0
- package/{lib/stacks → src/stacks/backends}/laravel/index.js +11 -3
- package/{lib/stacks → src/stacks/backends}/laravel/ui/blade.js +1 -0
- package/{lib/stacks → src/stacks/backends}/laravel/ui/index.js +1 -0
- package/{lib/stacks → src/stacks/backends}/laravel/ui/inertia-react.js +4 -2
- package/{lib/stacks → src/stacks/backends}/laravel/ui/livewire.js +1 -0
- package/{lib/stacks → src/stacks/backends}/laravel/ui/shared.js +1 -0
- package/src/stacks/backends/none/index.js +23 -0
- package/src/stacks/backends/postgres/ci.js +3 -0
- package/src/stacks/backends/postgres/create-files.js +21 -0
- package/src/stacks/backends/postgres/docker.js +3 -0
- package/src/stacks/backends/postgres/environment.js +3 -0
- package/src/stacks/backends/postgres/index.js +30 -0
- package/src/stacks/backends/springboot/ci.js +3 -0
- package/src/stacks/backends/springboot/create-files.js +91 -0
- package/src/stacks/backends/springboot/docker.js +3 -0
- package/src/stacks/backends/springboot/environment.js +3 -0
- package/src/stacks/backends/springboot/index.js +31 -0
- package/src/stacks/backends/supabase/ci.js +3 -0
- package/src/stacks/backends/supabase/create-files.js +52 -0
- package/src/stacks/backends/supabase/docker.js +3 -0
- package/src/stacks/backends/supabase/environment.js +3 -0
- package/src/stacks/backends/supabase/index.js +31 -0
- package/src/stacks/backends/supabase/native.js +14 -0
- package/src/stacks/compose-files.js +259 -0
- package/{lib/generator.js → src/stacks/create-project.js} +206 -57
- package/src/stacks/frontends/README.md +4 -0
- package/src/stacks/frontends/nextjs/ci.js +3 -0
- package/src/stacks/frontends/nextjs/create-files.js +46 -0
- package/src/stacks/frontends/nextjs/dependencies.js +5 -0
- package/src/stacks/frontends/nextjs/docker.js +3 -0
- package/src/stacks/frontends/nextjs/environment.js +7 -0
- package/src/stacks/frontends/nextjs/index.js +35 -0
- package/src/stacks/frontends/react-native/ci.js +3 -0
- package/src/stacks/frontends/react-native/create-files.js +28 -0
- package/src/stacks/frontends/react-native/dependencies.js +5 -0
- package/src/stacks/frontends/react-native/docker.js +5 -0
- package/src/stacks/frontends/react-native/environment.js +7 -0
- package/src/stacks/frontends/react-native/index.js +30 -0
- package/src/stacks/frontends/react-vite/ci.js +3 -0
- package/src/stacks/frontends/react-vite/create-files.js +27 -0
- package/src/stacks/frontends/react-vite/dependencies.js +5 -0
- package/src/stacks/frontends/react-vite/docker.js +3 -0
- package/src/stacks/frontends/react-vite/environment.js +8 -0
- package/src/stacks/frontends/react-vite/index.js +32 -0
- package/src/stacks/shared/capability-packs.js +31 -0
- package/{lib → src}/stacks/shared/contributions.js +1 -1
- package/src/stacks/shared/environment.js +38 -0
- package/src/stacks/shared/javascript-package.js +117 -0
- package/src/stacks/shared/testing-files.js +16 -0
- package/templates/ci/fastapi.yml +62 -0
- package/templates/docker/compose/postgres.yml +1 -1
- package/templates/docker/compose/springboot.yml +3 -3
- package/templates/docker/compose/supabase.yml +1 -1
- package/templates/docker/compose-prod/fastapi.yml +52 -0
- package/templates/docker/compose-prod/springboot.yml +20 -2
- package/templates/docker/dockerfile/fastapi.dev.dockerfile +9 -0
- package/templates/docker/dockerfile/fastapi.prod.dockerfile +11 -0
- package/templates/docker/dockerfile/nextjs.prod.dockerfile +1 -0
- package/templates/docker/dockerfile/springboot.prod.dockerfile +4 -1
- package/templates/docker/dockerfile/vite.prod.dockerfile +2 -1
- package/templates/makefile/fastapi.mk +97 -0
- package/docs/ARCHITECTURE.md +0 -118
- package/lib/banner.js +0 -45
- package/lib/constants.js +0 -3
- package/lib/doctor.js +0 -45
- package/lib/interview.js +0 -77
- package/lib/laravel-scaffold.js +0 -3
- package/lib/scaffold.js +0 -467
- package/lib/stacks/index.js +0 -8
- package/playbooks/concerns/zod.md +0 -174
- package/playbooks/devops/makefile.manifest.json +0 -10
- package/playbooks/devops/makefile.md +0 -556
- package/playbooks/styling/css-modules-extensions.md +0 -267
- package/playbooks/styling/css-modules.manifest.json +0 -11
- package/playbooks/universal/coding-rules.manifest.json +0 -12
- package/playbooks/universal/coding-rules.md +0 -281
- package/playbooks/universal/git-conventions.manifest.json +0 -10
- package/playbooks/universal/git-conventions.md +0 -186
- package/playbooks/universal/typescript.manifest.json +0 -11
- package/playbooks/universal/typescript.md +0 -272
- package/scripts/compatibility-matrix.mjs +0 -48
- /package/{playbooks/capabilities → library/development-tools}/ci/github-actions.md +0 -0
- /package/{playbooks/devops → library/development-tools/devops/pr-template}/pr-template.md +0 -0
- /package/{playbooks/capabilities/docker/docker.manifest.json → library/development-tools/docker/definition.json} +0 -0
- /package/{playbooks/capabilities → library/development-tools}/docker/overview.md +0 -0
- /package/{playbooks/capabilities → library/features}/auth/oidc-resource-server.md +0 -0
- /package/{playbooks/capabilities → library/features}/auth/spring-session.md +0 -0
- /package/{playbooks/capabilities/flyway/flyway.manifest.json → library/features/flyway/definition.json} +0 -0
- /package/{playbooks/capabilities → library/features}/flyway/environments.md +0 -0
- /package/{playbooks/capabilities → library/features}/flyway/migrations.md +0 -0
- /package/{playbooks/capabilities → library/features}/flyway/testing.md +0 -0
- /package/{playbooks/capabilities → library/features}/laravel/database.md +0 -0
- /package/{playbooks/capabilities → library/features}/laravel/migrations.md +0 -0
- /package/{playbooks/capabilities → library/features}/laravel/observability.md +0 -0
- /package/{playbooks/capabilities → library/features}/laravel/oidc-resource-server.md +0 -0
- /package/{playbooks/capabilities → library/features}/laravel/queues.md +0 -0
- /package/{playbooks/capabilities → library/features}/laravel/sanctum-spa.md +0 -0
- /package/{playbooks/capabilities → library/features}/laravel/scheduler.md +0 -0
- /package/{playbooks/capabilities → library/features}/laravel/session-auth.md +0 -0
- /package/{playbooks/capabilities → library/features}/laravel/storage-uploads.md +0 -0
- /package/{playbooks/capabilities → library/features}/postgresql/architecture.md +0 -0
- /package/{playbooks/capabilities/postgresql/postgresql.manifest.json → library/features/postgresql/definition.json} +0 -0
- /package/{playbooks/capabilities → library/features}/postgresql/migrations.md +0 -0
- /package/{playbooks/capabilities → library/features}/postgresql/schema-design.md +0 -0
- /package/{playbooks/capabilities → library/features}/postgresql/security.md +0 -0
- /package/{playbooks/capabilities → library/features}/postgresql/testing.md +0 -0
- /package/{playbooks/capabilities → library/features}/prisma/architecture.md +0 -0
- /package/{playbooks/capabilities/prisma/prisma.manifest.json → library/features/prisma/definition.json} +0 -0
- /package/{playbooks/capabilities → library/features}/prisma/migrations.md +0 -0
- /package/{playbooks/capabilities → library/features}/prisma/runtime.md +0 -0
- /package/{playbooks/capabilities → library/features}/prisma/schema.md +0 -0
- /package/{playbooks/capabilities → library/features}/prisma/testing.md +0 -0
- /package/{playbooks/capabilities → library/features}/supabase/architecture.md +0 -0
- /package/{playbooks/capabilities → library/features}/supabase/authentication.md +0 -0
- /package/{playbooks/capabilities/supabase/supabase.manifest.json → library/features/supabase/definition.json} +0 -0
- /package/{playbooks/capabilities → library/features}/supabase/expo.md +0 -0
- /package/{playbooks/capabilities → library/features}/supabase/migrations.md +0 -0
- /package/{playbooks/capabilities → library/features}/supabase/nextjs.md +0 -0
- /package/{playbooks/capabilities → library/features}/supabase/rls.md +0 -0
- /package/{playbooks/capabilities → library/features}/supabase/testing.md +0 -0
- /package/{playbooks/capabilities → library/features}/supabase/vite.md +0 -0
- /package/{playbooks → library/optional-features}/concerns/axios.md +0 -0
- /package/{playbooks → library/optional-features}/concerns/next-safe-action.md +0 -0
- /package/{playbooks → library/optional-features}/concerns/next-themes.md +0 -0
- /package/{playbooks → library/optional-features}/concerns/nuqs.md +0 -0
- /package/{playbooks → library/optional-features}/concerns/t3-env.md +0 -0
- /package/{playbooks → library/optional-features}/concerns/tanstack-query.md +0 -0
- /package/{playbooks → library/optional-features}/concerns/zustand.md +0 -0
- /package/{playbooks/styling/native-styles.manifest.json → library/optional-features/styling/native-styles/definition.json} +0 -0
- /package/{playbooks/styling → library/optional-features/styling/native-styles}/native-styles.md +0 -0
- /package/{playbooks/styling/tailwind.manifest.json → library/optional-features/styling/tailwind/definition.json} +0 -0
- /package/{playbooks/styling → library/optional-features/styling/tailwind}/tailwind-extensions.md +0 -0
- /package/{playbooks/platform → library/platforms}/laravel-ui/blade/architecture.md +0 -0
- /package/{playbooks/platform → library/platforms}/laravel-ui/blade/runtime.md +0 -0
- /package/{playbooks/platform → library/platforms}/laravel-ui/blade/security.md +0 -0
- /package/{playbooks/platform → library/platforms}/laravel-ui/blade/structure.md +0 -0
- /package/{playbooks/platform → library/platforms}/laravel-ui/blade/testing.md +0 -0
- /package/{playbooks/stack/laravel-ui.manifest.json → library/platforms/laravel-ui/definition.json} +0 -0
- /package/{playbooks/platform → library/platforms}/laravel-ui/inertia-react/architecture.md +0 -0
- /package/{playbooks/platform → library/platforms}/laravel-ui/inertia-react/runtime.md +0 -0
- /package/{playbooks/platform → library/platforms}/laravel-ui/inertia-react/security.md +0 -0
- /package/{playbooks/platform → library/platforms}/laravel-ui/inertia-react/structure.md +0 -0
- /package/{playbooks/platform → library/platforms}/laravel-ui/inertia-react/testing.md +0 -0
- /package/{playbooks/platform → library/platforms}/laravel-ui/livewire/architecture.md +0 -0
- /package/{playbooks/platform → library/platforms}/laravel-ui/livewire/runtime.md +0 -0
- /package/{playbooks/platform → library/platforms}/laravel-ui/livewire/security.md +0 -0
- /package/{playbooks/platform → library/platforms}/laravel-ui/livewire/structure.md +0 -0
- /package/{playbooks/platform → library/platforms}/laravel-ui/livewire/testing.md +0 -0
- /package/{playbooks/platform → library/platforms/mobile}/mobile.md +0 -0
- /package/{playbooks/platform → library/platforms/web}/web.md +0 -0
- /package/{playbooks/stack → library/stacks}/expo/architecture.md +0 -0
- /package/{playbooks/stack → library/stacks}/expo/runtime.md +0 -0
- /package/{playbooks/stack → library/stacks}/expo/security.md +0 -0
- /package/{playbooks/stack → library/stacks}/expo/structure.md +0 -0
- /package/{playbooks/stack → library/stacks}/expo/testing.md +0 -0
- /package/{playbooks/stack → library/stacks}/laravel/architecture.md +0 -0
- /package/{playbooks/stack/laravel.manifest.json → library/stacks/laravel/definition.json} +0 -0
- /package/{playbooks/stack → library/stacks}/laravel/runtime.md +0 -0
- /package/{playbooks/stack → library/stacks}/laravel/security.md +0 -0
- /package/{playbooks/stack → library/stacks}/laravel/structure.md +0 -0
- /package/{playbooks/stack → library/stacks}/laravel/testing.md +0 -0
- /package/{playbooks/stack → library/stacks}/nextjs/architecture.md +0 -0
- /package/{playbooks/stack → library/stacks}/nextjs/runtime.md +0 -0
- /package/{playbooks/stack → library/stacks}/nextjs/security.md +0 -0
- /package/{playbooks/stack → library/stacks}/nextjs/structure.md +0 -0
- /package/{playbooks/stack → library/stacks}/nextjs/testing.md +0 -0
- /package/{playbooks/stack/none.manifest.json → library/stacks/none/definition.json} +0 -0
- /package/{playbooks/stack → library/stacks}/react-vite/architecture.md +0 -0
- /package/{playbooks/stack → library/stacks}/react-vite/runtime.md +0 -0
- /package/{playbooks/stack → library/stacks}/react-vite/security.md +0 -0
- /package/{playbooks/stack → library/stacks}/react-vite/structure.md +0 -0
- /package/{playbooks/stack → library/stacks}/react-vite/testing.md +0 -0
- /package/{playbooks/stack → library/stacks}/springboot/architecture.md +0 -0
- /package/{playbooks/stack/springboot.manifest.json → library/stacks/springboot/definition.json} +0 -0
- /package/{playbooks/stack → library/stacks}/springboot/runtime.md +0 -0
- /package/{playbooks/stack → library/stacks}/springboot/security.md +0 -0
- /package/{playbooks/stack → library/stacks}/springboot/structure.md +0 -0
- /package/{playbooks/stack → library/stacks}/springboot/testing.md +0 -0
- /package/{playbooks/universal → library/universal/accessibility}/accessibility.md +0 -0
- /package/{playbooks/universal → library/universal/error-handling}/error-handling.md +0 -0
- /package/{playbooks/universal → library/universal/observability}/observability.md +0 -0
- /package/{playbooks/universal → library/universal/security}/security.md +0 -0
- /package/{lib → src/engine}/project-location.js +0 -0
- /package/{lib → src}/stacks/context.js +0 -0
- /package/{lib/stacks/contract.js → src/stacks/rules.js} +0 -0
- /package/{ci → templates/ci}/expo.yml +0 -0
- /package/{ci → templates/ci}/laravel.yml +0 -0
- /package/{ci → templates/ci}/nextjs.yml +0 -0
- /package/{ci → templates/ci}/springboot.yml +0 -0
- /package/{ci → templates/ci}/vite.yml +0 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"label": "React Native (Expo)",
|
|
5
5
|
"language": "TypeScript",
|
|
6
6
|
"platform": "mobile",
|
|
7
|
-
"appliesTo": { "backend": ["supabase", "springboot", "laravel", "none"] },
|
|
7
|
+
"appliesTo": { "backend": ["supabase", "springboot", "laravel", "none", "fastapi"] },
|
|
8
8
|
"port": 8081,
|
|
9
9
|
"needsDocker": false,
|
|
10
10
|
"frontendDir": "",
|
|
@@ -44,6 +44,6 @@
|
|
|
44
44
|
{ "id": "http-client", "required": false, "when": "The app adopts Axios for a REST API", "playbook": "concerns/axios.md", "sections": ["One Shared Client", "Service Calls apiClient, Hook Calls Service"] },
|
|
45
45
|
{ "id": "query", "required": false, "when": "The app needs cached remote server state", "playbook": "concerns/tanstack-query.md", "sections": ["Read Hook", "Mutation Hook", "QueryClient Setup"] },
|
|
46
46
|
{ "id": "state", "required": false, "when": "Shared state across multiple screens", "playbook": "concerns/zustand.md", "sections": ["Store Setup", "Auth Store Pattern"] },
|
|
47
|
-
{ "id": "validation", "required": false, "when": "Project has forms", "playbook": "concerns/zod.md", "sections": ["Schema First, Always", "React Native Form (React Hook Form + Controller)"] }
|
|
47
|
+
{ "id": "validation", "required": false, "when": "Project has forms", "playbook": "concerns/zod/validation.md", "sections": ["Schema First, Always", "React Native Form (React Hook Form + Controller)"] }
|
|
48
48
|
]
|
|
49
49
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# FastAPI Architecture
|
|
2
|
+
|
|
3
|
+
## Profiles
|
|
4
|
+
|
|
5
|
+
### Small
|
|
6
|
+
|
|
7
|
+
Use a compact application package with configuration, database, security, and route
|
|
8
|
+
modules. Do not add service/repository layers that have only one caller or split a
|
|
9
|
+
simple operation into ceremonial layers.
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
HTTP → Router → Service function → AsyncSession → PostgreSQL
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Medium (default)
|
|
16
|
+
|
|
17
|
+
Keep feature-oriented routers, services, repositories, schemas, and shared core
|
|
18
|
+
infrastructure explicit. Services own transaction boundaries and reusable operations.
|
|
19
|
+
Features communicate through clear service APIs rather than reaching into repositories.
|
|
20
|
+
|
|
21
|
+
### Large
|
|
22
|
+
|
|
23
|
+
Build bounded feature modules with explicit public module interfaces. A feature exposes
|
|
24
|
+
a small router/service API and keeps repository and schema implementation internal.
|
|
25
|
+
Verify no cycles, no access to internals, and only declared module dependencies with
|
|
26
|
+
the generated architecture-boundary tests. Large does not mean microservices.
|
|
27
|
+
|
|
28
|
+
## Dependency Direction
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
web/API → application operation → domain policy → persistence/external adapter
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- Routers translate HTTP and never touch the database session directly.
|
|
35
|
+
- Services do not return HTTP responses or depend on route details.
|
|
36
|
+
- Repositories contain persistence queries, not application policy.
|
|
37
|
+
- Cross-feature work calls a public operation or publishes a deliberate event.
|
|
38
|
+
- External side effects are not assumed successful merely because a transaction commits.
|
|
39
|
+
|
|
40
|
+
Start at the selected project baseline and let each feature create only the files it uses.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "fastapi",
|
|
3
|
+
"kind": "backend",
|
|
4
|
+
"label": "FastAPI",
|
|
5
|
+
"language": "Python",
|
|
6
|
+
"appliesTo": { "frontend": ["nextjs", "react", "react-native", "no-frontend"] },
|
|
7
|
+
"port": 8000,
|
|
8
|
+
"needsDocker": true,
|
|
9
|
+
"architectureProfiles": ["small", "medium", "large"],
|
|
10
|
+
"playbooks": [
|
|
11
|
+
"stack/fastapi/architecture.md",
|
|
12
|
+
"stack/fastapi/structure.md",
|
|
13
|
+
"stack/fastapi/runtime.md",
|
|
14
|
+
"stack/fastapi/security.md",
|
|
15
|
+
"stack/fastapi/testing.md",
|
|
16
|
+
"capabilities/sqlalchemy-alembic.md",
|
|
17
|
+
{ "file": "capabilities/auth/oidc-resource-server.md", "appliesWhen": { "authentication": "oidc" } }
|
|
18
|
+
],
|
|
19
|
+
"makefileTemplate": "fastapi",
|
|
20
|
+
"folders": [],
|
|
21
|
+
"deps": [],
|
|
22
|
+
"devDeps": [],
|
|
23
|
+
"env": ["API_URL", "DATABASE_URL", "POSTGRES_USER", "POSTGRES_PASSWORD", "POSTGRES_DB", "OIDC_ISSUER", "OIDC_AUDIENCE", "OIDC_ALGORITHMS", "OIDC_JWKS_URL", "CORS_ALLOWED_ORIGINS"],
|
|
24
|
+
"clientEnv": ["API_URL"],
|
|
25
|
+
"constraints": [
|
|
26
|
+
"FastAPI owns server-side business logic, authorization, and data access",
|
|
27
|
+
"Security starts deny-by-default; add authentication through OIDC bearer validation rather than hand-rolled token code",
|
|
28
|
+
"Application startup must not automatically migrate production databases"
|
|
29
|
+
],
|
|
30
|
+
"concerns": [
|
|
31
|
+
{ "id": "architecture", "required": true, "playbook": "stack/fastapi/architecture.md", "sections": ["Profiles", "Dependency Direction"] },
|
|
32
|
+
{ "id": "structure", "required": true, "playbook": "stack/fastapi/structure.md", "sections": ["Package by Feature"] },
|
|
33
|
+
{ "id": "runtime", "required": true, "playbook": "stack/fastapi/runtime.md", "sections": ["Configuration and Lifecycle", "Errors and Observability"] },
|
|
34
|
+
{ "id": "stack-security", "required": true, "playbook": "stack/fastapi/security.md", "sections": ["Authentication Models", "Authorization"] },
|
|
35
|
+
{ "id": "stack-testing", "required": true, "playbook": "stack/fastapi/testing.md", "sections": ["Test Layers"] },
|
|
36
|
+
{ "id": "persistence", "required": true, "playbook": "capabilities/sqlalchemy-alembic.md", "sections": ["Session Ownership", "Migrations"] },
|
|
37
|
+
{ "id": "oidc-auth", "required": true, "appliesWhen": { "authentication": "oidc" }, "playbook": "capabilities/auth/oidc-resource-server.md", "sections": ["Provider and API Responsibilities", "Required Tests"] }
|
|
38
|
+
]
|
|
39
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# FastAPI Runtime
|
|
2
|
+
|
|
3
|
+
## Configuration and Lifecycle
|
|
4
|
+
|
|
5
|
+
Configuration comes from validated Pydantic Settings and environment-specific deployment
|
|
6
|
+
values. The application exposes public `GET /health` and dependency-aware `GET /ready`
|
|
7
|
+
readiness separately. Readiness verifies dependencies required to serve traffic.
|
|
8
|
+
|
|
9
|
+
Manage dependencies with uv and a frozen lockfile (`uv sync --frozen`). Run with
|
|
10
|
+
Uvicorn. Keep schema changes owned by Alembic migrations invoked explicitly via
|
|
11
|
+
`alembic upgrade head`; application startup must not automatically migrate production
|
|
12
|
+
databases.
|
|
13
|
+
|
|
14
|
+
## Errors and Observability
|
|
15
|
+
|
|
16
|
+
Services raise typed application exceptions with stable error codes and no HTTP types.
|
|
17
|
+
Exception handlers map them to RFC 9457 problem details. Include a safe code and
|
|
18
|
+
trace ID; never expose stack traces, SQL, internal hosts, credentials, or sensitive fields.
|
|
19
|
+
|
|
20
|
+
Use structured PII-safe events. Do not log whole requests, passwords, tokens, cookies, or
|
|
21
|
+
email addresses by default.
|
|
22
|
+
|
|
23
|
+
Configure exact-origin CORS from `CORS_ALLOWED_ORIGINS`. Store uploads outside the
|
|
24
|
+
application tree under generated object keys; validate size and content and route
|
|
25
|
+
untrusted files through the product's scanning/quarantine process.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# FastAPI Security
|
|
2
|
+
|
|
3
|
+
## Authentication Models
|
|
4
|
+
|
|
5
|
+
The generated authentication choice is authoritative:
|
|
6
|
+
|
|
7
|
+
- `public`: no user accounts; generated application endpoints are intentionally public.
|
|
8
|
+
- `undecided`: health is public and every other endpoint is denied until auth is designed.
|
|
9
|
+
- `oidc`: an external identity provider owns login, refresh, rotation, and revocation;
|
|
10
|
+
FastAPI validates bearer issuer, audience, algorithm, JWKS signature, expiry, and claims
|
|
11
|
+
on every protected API request. Session authentication is not offered.
|
|
12
|
+
|
|
13
|
+
Never turn the API into a home-grown authorization server from a short JWT example.
|
|
14
|
+
|
|
15
|
+
## Authorization
|
|
16
|
+
|
|
17
|
+
Route dependencies provide a broad baseline. Enforce feature permissions and resource
|
|
18
|
+
ownership at the application operation or protected data boundary with explicit
|
|
19
|
+
dependencies. Test unauthenticated, authenticated-but-forbidden, and allowed cases.
|
|
20
|
+
|
|
21
|
+
- Keep public health endpoints separate from protected API routes.
|
|
22
|
+
- Configure OIDC issuer, audience, allowed algorithms, JWKS retrieval, and claim
|
|
23
|
+
validation from environment; deny by default.
|
|
24
|
+
- Configure exact-origin CORS. Never combine credentials with wildcard origin.
|
|
25
|
+
- Rate limit login, recovery, and other abuse-sensitive operations.
|
|
26
|
+
- Treat role claims as inputs to server policy, not proof of resource ownership.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# FastAPI Structure
|
|
2
|
+
|
|
3
|
+
## Package by Feature
|
|
4
|
+
|
|
5
|
+
Place the application entrypoint in the `app` package. Organize business code below it by
|
|
6
|
+
feature, never in one global router/service/repository layer.
|
|
7
|
+
|
|
8
|
+
```text
|
|
9
|
+
app/
|
|
10
|
+
├── main.py
|
|
11
|
+
├── core/ settings, database, security, logging (Medium/Large)
|
|
12
|
+
├── modules/status/ router, service, repository, schemas (Large)
|
|
13
|
+
├── features/status/ router, service, repository, schemas (Medium)
|
|
14
|
+
└── routes_health.py public health/readiness (Small)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Small may keep the few feature modules directly under `app/`. Medium uses the named
|
|
18
|
+
`features/` packages when multiple files make ownership clearer. Large exposes types in
|
|
19
|
+
the module base/`__init__.py` public interface and places implementation in submodules
|
|
20
|
+
as required by the generated boundary tests.
|
|
21
|
+
|
|
22
|
+
Backend-only projects live at the repository root. Paired backends live under `backend/`.
|
|
23
|
+
|
|
24
|
+
- Use explicit imports; re-export only the public module interface from `__init__.py`.
|
|
25
|
+
- Prefer Pydantic v2 models for transport schemas; keep ORM models persistence-only.
|
|
26
|
+
- Do not invent users, products, or other business entities in the baseline.
|
|
27
|
+
- Use database-native identity types and constraints deliberately.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# FastAPI Testing
|
|
2
|
+
|
|
3
|
+
## Test Layers
|
|
4
|
+
|
|
5
|
+
| Risk | Test |
|
|
6
|
+
|---|---|
|
|
7
|
+
| Pure policy/value object | pytest unit test |
|
|
8
|
+
| Service orchestration/error code | Focused unit test with boundary fakes |
|
|
9
|
+
| Router validation/error/security | HTTPX async test without a database |
|
|
10
|
+
| Custom repository/Alembic/constraints | PostgreSQL integration test |
|
|
11
|
+
| Feature module | Module integration test |
|
|
12
|
+
| Large boundaries | Generated boundary test (no internal imports) |
|
|
13
|
+
|
|
14
|
+
Do not use SQLite as proof that PostgreSQL queries or migrations work. Standard CRUD
|
|
15
|
+
methods need no dedicated test, but custom queries, constraints, locking, and migrations do.
|
|
16
|
+
|
|
17
|
+
Test behavior and risk rather than every public function or mock call. Authentication tests
|
|
18
|
+
cover missing bearer tokens and invalid issuer, audience, signature, expiry, and required
|
|
19
|
+
claims. Authorization tests include resource ownership, not roles alone.
|
|
20
|
+
|
|
21
|
+
Every profile runs `ruff check`, `ruff format --check`, `mypy`, and `pytest`. Full testing
|
|
22
|
+
runs PostgreSQL integration tests; Large additionally fails on cycles and access to
|
|
23
|
+
module internals.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"label": "Next.js",
|
|
5
5
|
"language": "TypeScript",
|
|
6
6
|
"platform": "web",
|
|
7
|
-
"appliesTo": { "backend": ["none", "supabase", "springboot", "postgres", "laravel"] },
|
|
7
|
+
"appliesTo": { "backend": ["none", "supabase", "springboot", "postgres", "laravel", "fastapi"] },
|
|
8
8
|
"port": 3000,
|
|
9
9
|
"needsDocker": false,
|
|
10
10
|
"frontendDir": "",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
{ "id": "runtime", "required": true, "playbook": "stack/nextjs/runtime.md", "sections": ["Server and Client", "Caching and Mutations"] },
|
|
39
39
|
{ "id": "stack-security", "required": true, "playbook": "stack/nextjs/security.md", "sections": ["Authorization", "Sessions"] },
|
|
40
40
|
{ "id": "stack-testing", "required": true, "playbook": "stack/nextjs/testing.md", "sections": ["Test Layers"] },
|
|
41
|
-
{ "id": "validation", "required": false, "when": "Project has forms / runtime input", "playbook": "concerns/zod.md", "sections": ["Schema First, Always", "Zod Schema Placement"] },
|
|
41
|
+
{ "id": "validation", "required": false, "when": "Project has forms / runtime input", "playbook": "concerns/zod/validation.md", "sections": ["Schema First, Always", "Zod Schema Placement"] },
|
|
42
42
|
{ "id": "query", "required": false, "when": "Client needs cached server state", "playbook": "concerns/tanstack-query.md", "sections": ["Read Hook", "Mutation Hook"] },
|
|
43
43
|
{ "id": "state", "required": false, "when": "Shared non-server UI state", "playbook": "concerns/zustand.md", "sections": ["Store Setup"] },
|
|
44
44
|
{ "id": "env", "required": false, "when": "Validating env vars at build time", "playbook": "concerns/t3-env.md", "sections": ["Setup"] },
|
package/{playbooks/stack/react-vite.manifest.json → library/stacks/react-vite/definition.json}
RENAMED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"label": "React + Vite",
|
|
5
5
|
"language": "TypeScript",
|
|
6
6
|
"platform": "web",
|
|
7
|
-
"appliesTo": { "backend": ["none", "supabase", "springboot", "laravel"] },
|
|
7
|
+
"appliesTo": { "backend": ["none", "supabase", "springboot", "laravel", "fastapi"] },
|
|
8
8
|
"port": 5173,
|
|
9
9
|
"needsDocker": false,
|
|
10
10
|
"frontendDir": "frontend",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
{ "id": "stack-security", "required": true, "playbook": "stack/react-vite/security.md", "sections": ["Browser Trust Boundary"] },
|
|
40
40
|
{ "id": "stack-testing", "required": true, "playbook": "stack/react-vite/testing.md", "sections": ["Test Layers"] },
|
|
41
41
|
{ "id": "http-client", "required": false, "when": "The app adopts Axios instead of the native fetch client", "playbook": "concerns/axios.md", "sections": ["One Shared Client", "Service Calls apiClient, Hook Calls Service"] },
|
|
42
|
-
{ "id": "validation", "required": false, "when": "Project has forms / runtime input", "playbook": "concerns/zod.md", "sections": ["Schema First, Always", "Web Form (React Hook Form)"] },
|
|
42
|
+
{ "id": "validation", "required": false, "when": "Project has forms / runtime input", "playbook": "concerns/zod/validation.md", "sections": ["Schema First, Always", "Web Form (React Hook Form)"] },
|
|
43
43
|
{ "id": "query", "required": false, "when": "Client needs cached server state", "playbook": "concerns/tanstack-query.md", "sections": ["Read Hook", "Mutation Hook"] },
|
|
44
44
|
{ "id": "state", "required": false, "when": "Shared UI state across pages", "playbook": "concerns/zustand.md", "sections": ["Store Setup"] }
|
|
45
45
|
]
|
|
@@ -9,11 +9,15 @@
|
|
|
9
9
|
"springModulith": "2.0.8",
|
|
10
10
|
"runtimes": {
|
|
11
11
|
"node": "24.20.0",
|
|
12
|
+
"nodeMinimum": "22.14.0",
|
|
13
|
+
"npmMinimum": "11.19.0",
|
|
12
14
|
"java": "21",
|
|
13
15
|
"maven": "3.9.16",
|
|
14
16
|
"postgres": "16",
|
|
15
17
|
"php": "8.5.10",
|
|
16
|
-
"composer": "2.10.3"
|
|
18
|
+
"composer": "2.10.3",
|
|
19
|
+
"python": "3.14.7",
|
|
20
|
+
"uv": "0.12.10"
|
|
17
21
|
},
|
|
18
22
|
"images": {
|
|
19
23
|
"node": {
|
|
@@ -43,8 +47,26 @@
|
|
|
43
47
|
"composer": {
|
|
44
48
|
"repository": "composer",
|
|
45
49
|
"tag": "2.10.3"
|
|
50
|
+
},
|
|
51
|
+
"python": {
|
|
52
|
+
"repository": "python",
|
|
53
|
+
"tag": "3.14.7-slim"
|
|
46
54
|
}
|
|
47
55
|
},
|
|
56
|
+
"pythonPackages": {
|
|
57
|
+
"alembic": "1.19.2",
|
|
58
|
+
"asyncpg": "0.31.0",
|
|
59
|
+
"fastapi": "0.141.1",
|
|
60
|
+
"httpx": "0.28.1",
|
|
61
|
+
"mypy": "2.3.1",
|
|
62
|
+
"pydantic-settings": "2.15.0",
|
|
63
|
+
"pyjwt": "2.13.0",
|
|
64
|
+
"pytest": "9.1.1",
|
|
65
|
+
"pytest-asyncio": "1.4.0",
|
|
66
|
+
"ruff": "0.16.6",
|
|
67
|
+
"sqlalchemy": "2.0.52",
|
|
68
|
+
"uvicorn": "0.52.4"
|
|
69
|
+
},
|
|
48
70
|
"composerPackages": {
|
|
49
71
|
"auth0/login": "7.22.0",
|
|
50
72
|
"fakerphp/faker": "1.24.1",
|
|
@@ -125,11 +147,15 @@
|
|
|
125
147
|
"springModulith": "2.0.8",
|
|
126
148
|
"runtimes": {
|
|
127
149
|
"node": "24.20.0",
|
|
150
|
+
"nodeMinimum": "22.14.0",
|
|
151
|
+
"npmMinimum": "11.19.0",
|
|
128
152
|
"java": "21",
|
|
129
153
|
"maven": "3.9.16",
|
|
130
154
|
"postgres": "16",
|
|
131
155
|
"php": "8.5.10",
|
|
132
|
-
"composer": "2.10.3"
|
|
156
|
+
"composer": "2.10.3",
|
|
157
|
+
"python": "3.13.15",
|
|
158
|
+
"uv": "0.12.10"
|
|
133
159
|
},
|
|
134
160
|
"images": {
|
|
135
161
|
"node": {
|
|
@@ -159,8 +185,26 @@
|
|
|
159
185
|
"composer": {
|
|
160
186
|
"repository": "composer",
|
|
161
187
|
"tag": "2.10.3"
|
|
188
|
+
},
|
|
189
|
+
"python": {
|
|
190
|
+
"repository": "python",
|
|
191
|
+
"tag": "3.13.15-slim"
|
|
162
192
|
}
|
|
163
193
|
},
|
|
194
|
+
"pythonPackages": {
|
|
195
|
+
"alembic": "1.19.2",
|
|
196
|
+
"asyncpg": "0.31.0",
|
|
197
|
+
"fastapi": "0.141.1",
|
|
198
|
+
"httpx": "0.28.1",
|
|
199
|
+
"mypy": "2.3.1",
|
|
200
|
+
"pydantic-settings": "2.15.0",
|
|
201
|
+
"pyjwt": "2.13.0",
|
|
202
|
+
"pytest": "9.1.1",
|
|
203
|
+
"pytest-asyncio": "1.4.0",
|
|
204
|
+
"ruff": "0.16.6",
|
|
205
|
+
"sqlalchemy": "2.0.52",
|
|
206
|
+
"uvicorn": "0.52.4"
|
|
207
|
+
},
|
|
164
208
|
"composerPackages": {
|
|
165
209
|
"auth0/login": "7.22.0",
|
|
166
210
|
"fakerphp/faker": "1.24.1",
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"id": "accessibility-baseline",
|
|
3
3
|
"kind": "universal",
|
|
4
4
|
"label": "Accessibility Baseline",
|
|
5
|
+
"file": "universal/accessibility.md",
|
|
5
6
|
"required": true,
|
|
6
7
|
"folders": [],
|
|
7
8
|
"concerns": [
|
|
8
9
|
{ "id": "accessibility", "required": true, "sections": ["Semantic Structure", "Keyboard and Focus", "Forms and Authentication", "Accessibility Testing"] }
|
|
9
10
|
]
|
|
10
11
|
}
|
|
11
|
-
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "coding-rules",
|
|
3
|
+
"kind": "universal",
|
|
4
|
+
"label": "Coding Rules",
|
|
5
|
+
"playbooks": ["universal/coding-rules/naming.md", "universal/coding-rules/hygiene.md"],
|
|
6
|
+
"required": true,
|
|
7
|
+
"folders": [],
|
|
8
|
+
"devDeps": ["prettier"],
|
|
9
|
+
"concerns": [
|
|
10
|
+
{ "id": "naming", "required": true, "playbook": "universal/coding-rules/naming.md", "sections": ["Naming", "Functions", "Imports", "Constants"] },
|
|
11
|
+
{ "id": "no-debug", "required": true, "playbook": "universal/coding-rules/hygiene.md", "sections": ["No Debug Code in Commits", "One Thing Per File"] }
|
|
12
|
+
]
|
|
13
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Code hygiene
|
|
2
|
+
|
|
3
|
+
## No Debug Code in Commits
|
|
4
|
+
|
|
5
|
+
Remove temporary logging, breakpoints, fixtures, bypasses, and commented-out implementations. Retain structured operational logging only when it has defined level, fields, privacy handling, and ownership.
|
|
6
|
+
|
|
7
|
+
## One Thing Per File
|
|
8
|
+
|
|
9
|
+
A file should have one clear reason to change. Keep tightly coupled helpers beside their owner, but split unrelated components, routes, services, or policies. Do not create one-line files merely to satisfy this rule.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Naming and structure
|
|
2
|
+
|
|
3
|
+
## Naming
|
|
4
|
+
|
|
5
|
+
Use names that describe domain intent. Avoid unexplained abbreviations, generic `data`/`utils` modules, and names that repeat their containing folder.
|
|
6
|
+
|
|
7
|
+
## Functions
|
|
8
|
+
|
|
9
|
+
Keep functions focused, make side effects visible, validate at boundaries, and return early for invalid states.
|
|
10
|
+
|
|
11
|
+
## Imports
|
|
12
|
+
|
|
13
|
+
Group platform, external, and local imports consistently. Respect architecture boundaries and remove unused imports.
|
|
14
|
+
|
|
15
|
+
## Constants
|
|
16
|
+
|
|
17
|
+
Name shared constants by meaning, keep feature-local values near their owner, and do not disguise mutable state as a constant.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Git commits
|
|
2
|
+
|
|
3
|
+
## Commit Convention
|
|
4
|
+
|
|
5
|
+
Use `type(scope): imperative summary`. Each commit should represent one coherent, testable change and must not include secrets, generated noise, debug code, or unrelated formatting.
|
|
6
|
+
|
|
7
|
+
Explain motivation and migration impact in the body when the diff alone is insufficient.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "git-conventions",
|
|
3
|
+
"kind": "universal",
|
|
4
|
+
"label": "Git Conventions",
|
|
5
|
+
"playbooks": ["universal/git-conventions/branches.md", "universal/git-conventions/commits.md", "universal/git-conventions/workflow.md"],
|
|
6
|
+
"required": true,
|
|
7
|
+
"folders": [],
|
|
8
|
+
"concerns": [
|
|
9
|
+
{ "id": "git-branches", "required": true, "playbook": "universal/git-conventions/branches.md", "sections": ["Branch Structure"] },
|
|
10
|
+
{ "id": "git-commits", "required": true, "playbook": "universal/git-conventions/commits.md", "sections": ["Commit Convention"] },
|
|
11
|
+
{ "id": "git-workflow", "required": true, "playbook": "universal/git-conventions/workflow.md", "sections": ["Daily Workflow"] }
|
|
12
|
+
]
|
|
13
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Git workflow
|
|
2
|
+
|
|
3
|
+
## Daily Workflow
|
|
4
|
+
|
|
5
|
+
Inspect status and upstream changes before editing. Preserve user work, stage deliberately, review the staged diff, and run risk-appropriate checks before committing. Do not push, merge, rewrite shared history, or create releases without authorization.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# TypeScript boundaries
|
|
2
|
+
|
|
3
|
+
## Strict Mode — Always On
|
|
4
|
+
|
|
5
|
+
Keep `strict` enabled. Model inputs at trust boundaries as `unknown`, validate them, then pass typed values inward. Do not weaken compiler options for one failing file.
|
|
6
|
+
|
|
7
|
+
## No any
|
|
8
|
+
|
|
9
|
+
Avoid `any`. Prefer `unknown`, generics, discriminated unions, or a narrow local type. If an external library forces an escape hatch, isolate and document it at the adapter boundary.
|
|
10
|
+
|
|
11
|
+
## Type vs Interface
|
|
12
|
+
|
|
13
|
+
Use interfaces for extendable object contracts and types for unions, intersections, mapped types, and aliases. Consistency within a feature matters more than stylistic conversion.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "typescript",
|
|
3
|
+
"kind": "universal",
|
|
4
|
+
"label": "TypeScript",
|
|
5
|
+
"playbooks": ["universal/typescript/boundaries.md", "universal/typescript/errors.md", "universal/typescript/patterns.md"],
|
|
6
|
+
"required": true,
|
|
7
|
+
"folders": [],
|
|
8
|
+
"concerns": [
|
|
9
|
+
{ "id": "typescript-strict", "required": true, "playbook": "universal/typescript/boundaries.md", "sections": ["Strict Mode — Always On", "No any", "Type vs Interface"] },
|
|
10
|
+
{ "id": "validation", "required": false, "when": "Project validates external/runtime input", "playbook": "universal/typescript/patterns.md", "sections": ["Zod for Runtime Validation"] }
|
|
11
|
+
]
|
|
12
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# TypeScript patterns
|
|
2
|
+
|
|
3
|
+
## Zod for Runtime Validation
|
|
4
|
+
|
|
5
|
+
Static types do not validate runtime data. Parse environment variables, requests, storage, and third-party responses at entry points. Export the inferred type from the schema instead of maintaining a duplicate interface.
|
|
6
|
+
|
|
7
|
+
Prefer small pure functions, explicit return types on public APIs, `satisfies` for configuration, and immutable inputs where mutation is not part of the contract.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-win-project",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Project scaffolding CLI by Win",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -13,15 +13,12 @@
|
|
|
13
13
|
},
|
|
14
14
|
"files": [
|
|
15
15
|
"index.js",
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"playbooks",
|
|
19
|
-
"ci",
|
|
16
|
+
"src",
|
|
17
|
+
"library",
|
|
20
18
|
"templates",
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"docs
|
|
24
|
-
"docs/DEPENDENCY_MAINTENANCE.md",
|
|
19
|
+
"checks",
|
|
20
|
+
"public/logo.svg",
|
|
21
|
+
"docs",
|
|
25
22
|
"README.md",
|
|
26
23
|
"LICENSE"
|
|
27
24
|
],
|
|
@@ -29,13 +26,15 @@
|
|
|
29
26
|
"start": "node index.js",
|
|
30
27
|
"doctor": "node index.js doctor",
|
|
31
28
|
"test": "vitest run",
|
|
32
|
-
"validate:content": "node
|
|
33
|
-
"
|
|
34
|
-
"matrix:
|
|
35
|
-
"
|
|
29
|
+
"validate:content": "node checks/check-library.js",
|
|
30
|
+
"package:check": "node checks/check-package.js",
|
|
31
|
+
"matrix:smoke": "node checks/check-compatibility.js --scope=smoke",
|
|
32
|
+
"matrix:full": "node checks/check-compatibility.js --scope=full",
|
|
33
|
+
"verify:generated": "node checks/check-generated-project.js"
|
|
36
34
|
},
|
|
37
35
|
"engines": {
|
|
38
|
-
"node": ">=
|
|
36
|
+
"node": ">=22.14",
|
|
37
|
+
"npm": ">=11.19"
|
|
39
38
|
},
|
|
40
39
|
"dependencies": {
|
|
41
40
|
"chalk": "5.6.2",
|
|
@@ -44,6 +43,6 @@
|
|
|
44
43
|
"ora": "7.0.1"
|
|
45
44
|
},
|
|
46
45
|
"devDependencies": {
|
|
47
|
-
"vitest": "
|
|
46
|
+
"vitest": "5.0.0"
|
|
48
47
|
}
|
|
49
48
|
}
|
package/public/logo.svg
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" role="img" aria-label="W1N Project logo">
|
|
2
|
+
<title>W1N Project logo</title>
|
|
3
|
+
<style>
|
|
4
|
+
.bracket { fill: #ffffff; }
|
|
5
|
+
.accent { fill: #bdfa02; }
|
|
6
|
+
</style>
|
|
7
|
+
<circle cx="128" cy="128" r="128" fill="#0a0a0a" />
|
|
8
|
+
<g class="brackets">
|
|
9
|
+
<path class="bracket" d="M 90.00 183.50 L 85.50 180.00 L 81.50 162.00 L 84.50 155.00 L 128.00 93.50 L 152.00 93.50 L 153.50 96.00 L 149.50 102.00 L 90.00 183.50 Z" />
|
|
10
|
+
<path class="bracket" d="M 59.00 162.50 L 46.00 162.50 L 12.50 130.00 L 12.50 126.00 L 46.00 93.50 L 59.00 93.50 L 60.50 102.00 L 34.50 128.00 L 60.50 154.00 L 59.00 162.50 Z" />
|
|
11
|
+
<path class="bracket" d="M 209.00 162.50 L 196.00 162.50 L 194.50 154.00 L 220.50 127.00 L 194.50 102.00 L 196.00 93.50 L 211.00 94.50 L 242.50 126.00 L 241.50 131.00 L 209.00 162.50 Z" />
|
|
12
|
+
<path class="bracket" d="M 82.00 151.50 L 79.50 151.00 L 78.50 147.00 L 64.50 79.00 L 64.50 74.00 L 67.00 71.50 L 86.00 71.50 L 89.50 75.00 L 100.50 124.00 L 82.00 151.50 Z" />
|
|
13
|
+
<path class="bracket" d="M 121.00 183.50 L 114.00 183.50 L 111.50 181.00 L 108.50 163.00 L 124.50 141.00 L 127.00 140.50 L 132.50 162.00 L 121.00 183.50 Z" />
|
|
14
|
+
</g>
|
|
15
|
+
<g class="accents">
|
|
16
|
+
<path class="accent" d="M 149.00 183.50 L 128.00 183.50 L 126.50 180.00 L 165.50 91.00 L 150.50 89.00 L 171.00 71.50 L 195.00 71.50 L 195.50 78.00 L 149.00 183.50 Z" />
|
|
17
|
+
<path class="accent" d="M 225.00 183.50 L 173.00 183.50 L 171.50 174.00 L 225.00 172.50 L 225.00 183.50 Z" />
|
|
18
|
+
</g>
|
|
19
|
+
</svg>
|