@dewtech/dare-cli 3.3.0 → 3.4.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 +21 -0
- package/README.md +764 -764
- package/dist/__tests__/confidence.test.js +13 -13
- package/dist/__tests__/dag-converter.test.js +56 -56
- package/dist/__tests__/mcp-server/server.test.js +3 -16
- package/dist/__tests__/mcp-server/server.test.js.map +1 -1
- package/dist/__tests__/project-generator.test.js +2 -2
- package/dist/__tests__/project-generator.test.js.map +1 -1
- package/dist/__tests__/refine.test.js +49 -49
- package/dist/__tests__/reverse-collection.test.js +6 -6
- package/dist/__tests__/review.test.js +38 -38
- package/dist/__tests__/security-hardening.test.d.ts +2 -0
- package/dist/__tests__/security-hardening.test.d.ts.map +1 -0
- package/dist/__tests__/security-hardening.test.js +101 -0
- package/dist/__tests__/security-hardening.test.js.map +1 -0
- package/dist/__tests__/validate.test.js +65 -65
- package/dist/bin/dare.js +0 -0
- package/dist/commands/__tests__/init-validation.test.d.ts +2 -0
- package/dist/commands/__tests__/init-validation.test.d.ts.map +1 -0
- package/dist/commands/__tests__/init-validation.test.js +81 -0
- package/dist/commands/__tests__/init-validation.test.js.map +1 -0
- package/dist/commands/__tests__/init.integration.spec.js +6 -4
- package/dist/commands/__tests__/init.integration.spec.js.map +1 -1
- package/dist/commands/__tests__/init.spec.d.ts +2 -0
- package/dist/commands/__tests__/init.spec.d.ts.map +1 -0
- package/dist/commands/__tests__/init.spec.js +88 -0
- package/dist/commands/__tests__/init.spec.js.map +1 -0
- package/dist/commands/blueprint.js +122 -122
- package/dist/commands/design.js +20 -20
- package/dist/commands/init-validation.d.ts +22 -0
- package/dist/commands/init-validation.d.ts.map +1 -0
- package/dist/commands/init-validation.js +54 -0
- package/dist/commands/init-validation.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +26 -10
- package/dist/commands/init.js.map +1 -1
- package/dist/graphrag/graph-rag.js +24 -24
- package/dist/mcp-server/__tests__/auth.test.d.ts +2 -0
- package/dist/mcp-server/__tests__/auth.test.d.ts.map +1 -0
- package/dist/mcp-server/__tests__/auth.test.js +72 -0
- package/dist/mcp-server/__tests__/auth.test.js.map +1 -0
- package/dist/mcp-server/__tests__/boot-config.test.d.ts +2 -0
- package/dist/mcp-server/__tests__/boot-config.test.d.ts.map +1 -0
- package/dist/mcp-server/__tests__/boot-config.test.js +29 -0
- package/dist/mcp-server/__tests__/boot-config.test.js.map +1 -0
- package/dist/mcp-server/__tests__/error-sanitize.test.d.ts +2 -0
- package/dist/mcp-server/__tests__/error-sanitize.test.d.ts.map +1 -0
- package/dist/mcp-server/__tests__/error-sanitize.test.js +66 -0
- package/dist/mcp-server/__tests__/error-sanitize.test.js.map +1 -0
- package/dist/mcp-server/__tests__/path-confinement.test.d.ts +2 -0
- package/dist/mcp-server/__tests__/path-confinement.test.d.ts.map +1 -0
- package/dist/mcp-server/__tests__/path-confinement.test.js +135 -0
- package/dist/mcp-server/__tests__/path-confinement.test.js.map +1 -0
- package/dist/mcp-server/bin/server.js +18 -6
- package/dist/mcp-server/bin/server.js.map +1 -1
- package/dist/mcp-server/boot-config.d.ts +6 -0
- package/dist/mcp-server/boot-config.d.ts.map +1 -0
- package/dist/mcp-server/boot-config.js +17 -0
- package/dist/mcp-server/boot-config.js.map +1 -0
- package/dist/mcp-server/middleware/auth.d.ts +10 -0
- package/dist/mcp-server/middleware/auth.d.ts.map +1 -0
- package/dist/mcp-server/middleware/auth.js +44 -0
- package/dist/mcp-server/middleware/auth.js.map +1 -0
- package/dist/mcp-server/middleware/cors.d.ts +6 -0
- package/dist/mcp-server/middleware/cors.d.ts.map +1 -0
- package/dist/mcp-server/middleware/cors.js +30 -0
- package/dist/mcp-server/middleware/cors.js.map +1 -0
- package/dist/mcp-server/middleware/error-handler.d.ts +11 -0
- package/dist/mcp-server/middleware/error-handler.d.ts.map +1 -0
- package/dist/mcp-server/middleware/error-handler.js +14 -0
- package/dist/mcp-server/middleware/error-handler.js.map +1 -0
- package/dist/mcp-server/server.d.ts +7 -2
- package/dist/mcp-server/server.d.ts.map +1 -1
- package/dist/mcp-server/server.js +185 -105
- package/dist/mcp-server/server.js.map +1 -1
- package/dist/skills/registry-mock.json +109 -109
- package/dist/skills/tests/manifest.spec.js +20 -20
- package/dist/stacks/__tests__/dna-emitter.spec.js +6 -6
- package/dist/stacks/dna-emitter.js +69 -69
- package/dist/stacks/ruby-rails-8/scaffold.js +15 -15
- package/dist/utils/project-generator.d.ts.map +1 -1
- package/dist/utils/project-generator.js +254 -252
- package/dist/utils/project-generator.js.map +1 -1
- package/dist/utils/stack-bootstrap.js +371 -371
- package/dist/utils/templates.js +394 -394
- package/dist/verification/__tests__/anti-tamper.test.js +13 -13
- package/package.json +96 -93
- package/templates/DARE-dag-example.yaml +280 -280
- package/templates/UPDATE-MANIFEST.json +68 -68
- package/templates/backend/node-nestjs/.env.example +9 -9
- package/templates/backend/node-nestjs/nest-cli.json +8 -8
- package/templates/backend/node-nestjs/package.json +50 -50
- package/templates/backend/node-nestjs/src/app.controller.ts +12 -12
- package/templates/backend/node-nestjs/src/app.module.ts +15 -15
- package/templates/backend/node-nestjs/src/app.service.ts +8 -8
- package/templates/backend/node-nestjs/src/main.ts +24 -24
- package/templates/backend/node-nestjs/tsconfig.json +21 -21
- package/templates/backend/php-laravel/.env.example +22 -22
- package/templates/backend/php-laravel/app/Http/Controllers/HealthController.php +15 -15
- package/templates/backend/php-laravel/composer.json +40 -40
- package/templates/backend/python-fastapi/.env.example +4 -4
- package/templates/backend/python-fastapi/app/api/router.py +8 -8
- package/templates/backend/python-fastapi/app/core/config.py +20 -20
- package/templates/backend/python-fastapi/main.py +35 -35
- package/templates/backend/python-fastapi/requirements.txt +13 -13
- package/templates/backend/rust-axum/.env.example +3 -3
- package/templates/backend/rust-axum/Cargo.toml +23 -23
- package/templates/backend/rust-axum/src/errors.rs +30 -30
- package/templates/backend/rust-axum/src/main.rs +32 -32
- package/templates/backend/rust-axum/src/routes.rs +6 -6
- package/templates/frontend/leptos-csr/.cargo/config.toml +2 -2
- package/templates/frontend/leptos-csr/Cargo.toml +16 -16
- package/templates/frontend/leptos-csr/Trunk.toml +10 -10
- package/templates/frontend/leptos-csr/index.html +11 -11
- package/templates/frontend/leptos-csr/src/lib.rs +20 -20
- package/templates/frontend/leptos-csr/style/main.scss +19 -19
- package/templates/frontend/leptos-fullstack/.cargo/config.toml +4 -4
- package/templates/frontend/leptos-fullstack/Cargo.toml +56 -56
- package/templates/frontend/leptos-fullstack/src/app.rs +49 -49
- package/templates/frontend/leptos-fullstack/src/lib.rs +9 -9
- package/templates/frontend/leptos-fullstack/src/main.rs +29 -29
- package/templates/frontend/leptos-fullstack/style/main.scss +19 -19
- package/templates/frontend/react/index.html +12 -12
- package/templates/frontend/react/package.json +35 -35
- package/templates/frontend/react/src/App.tsx +25 -25
- package/templates/frontend/react/src/main.tsx +9 -9
- package/templates/frontend/vue/package.json +32 -32
- package/templates/frontend/vue/src/App.vue +7 -7
- package/templates/frontend/vue/src/main.ts +10 -10
- package/templates/frontend/vue/src/router/index.ts +14 -14
- package/templates/frontend/vue/src/views/HomeView.vue +6 -6
- package/templates/hooks/pre-commit-dare-validate +24 -24
- package/templates/ide/antigravity/.agents/skills/dare-ax/SKILL.md +152 -152
- package/templates/ide/antigravity/.agents/skills/dare-bench/SKILL.md +21 -21
- package/templates/ide/antigravity/.agents/skills/dare-blueprint/SKILL.md +368 -368
- package/templates/ide/antigravity/.agents/skills/dare-bootstrap/SKILL.md +32 -32
- package/templates/ide/antigravity/.agents/skills/dare-bugfix-design/SKILL.md +76 -76
- package/templates/ide/antigravity/.agents/skills/dare-dag/SKILL.md +32 -32
- package/templates/ide/antigravity/.agents/skills/dare-dag-build/SKILL.md +154 -154
- package/templates/ide/antigravity/.agents/skills/dare-dag-run/SKILL.md +130 -130
- package/templates/ide/antigravity/.agents/skills/dare-dag-runner/SKILL.md +203 -203
- package/templates/ide/antigravity/.agents/skills/dare-design/SKILL.md +180 -180
- package/templates/ide/antigravity/.agents/skills/dare-discover/SKILL.md +33 -33
- package/templates/ide/antigravity/.agents/skills/dare-dna/SKILL.md +63 -63
- package/templates/ide/antigravity/.agents/skills/dare-docker/SKILL.md +315 -315
- package/templates/ide/antigravity/.agents/skills/dare-execute/SKILL.md +264 -264
- package/templates/ide/antigravity/.agents/skills/dare-feature-design/SKILL.md +74 -74
- package/templates/ide/antigravity/.agents/skills/dare-frontend-design/SKILL.md +192 -192
- package/templates/ide/antigravity/.agents/skills/dare-graph/SKILL.md +35 -35
- package/templates/ide/antigravity/.agents/skills/dare-info/SKILL.md +31 -31
- package/templates/ide/antigravity/.agents/skills/dare-init/SKILL.md +35 -35
- package/templates/ide/antigravity/.agents/skills/dare-laravel-api/SKILL.md +337 -337
- package/templates/ide/antigravity/.agents/skills/dare-layered-design/SKILL.md +166 -166
- package/templates/ide/antigravity/.agents/skills/dare-llm-integration/SKILL.md +217 -217
- package/templates/ide/antigravity/.agents/skills/dare-migrate/SKILL.md +61 -61
- package/templates/ide/antigravity/.agents/skills/dare-quality-telemetry/SKILL.md +187 -187
- package/templates/ide/antigravity/.agents/skills/dare-realtime/SKILL.md +217 -217
- package/templates/ide/antigravity/.agents/skills/dare-refine/SKILL.md +114 -114
- package/templates/ide/antigravity/.agents/skills/dare-reverse/SKILL.md +108 -108
- package/templates/ide/antigravity/.agents/skills/dare-review/SKILL.md +111 -111
- package/templates/ide/antigravity/.agents/skills/dare-rust-leptos/SKILL.md +263 -263
- package/templates/ide/antigravity/.agents/skills/dare-rust-workspace/SKILL.md +275 -275
- package/templates/ide/antigravity/.agents/skills/dare-security/SKILL.md +274 -274
- package/templates/ide/antigravity/.agents/skills/dare-skill/SKILL.md +35 -35
- package/templates/ide/antigravity/.agents/skills/dare-tasks/SKILL.md +265 -265
- package/templates/ide/antigravity/.agents/skills/dare-telemetry/SKILL.md +188 -188
- package/templates/ide/antigravity/.agents/skills/dare-update/SKILL.md +33 -33
- package/templates/ide/antigravity/.agents/skills/dare-validate/SKILL.md +33 -33
- package/templates/ide/antigravity/.agents/skills/dare-welcome/SKILL.md +30 -30
- package/templates/ide/antigravity/.agents/skills/skill-fastapi-api/SKILL.md +343 -343
- package/templates/ide/antigravity/.agents/skills/skill-go-gin-api/SKILL.md +377 -377
- package/templates/ide/antigravity/.agents/skills/skill-mcp-server/SKILL.md +382 -382
- package/templates/ide/antigravity/.agents/skills/skill-nestjs-api/SKILL.md +326 -326
- package/templates/ide/antigravity/.agents/skills/skill-rails-api/SKILL.md +393 -393
- package/templates/ide/antigravity/templates/BLUEPRINT-template.md +193 -193
- package/templates/ide/antigravity/templates/DESIGN-template.md +129 -129
- package/templates/ide/antigravity/templates/TASK-SPEC-template.md +141 -141
- package/templates/ide/antigravity/templates/TASKS-template.md +26 -26
- package/templates/ide/antigravity/templates/TELEMETRY-template.md +125 -125
- package/templates/ide/claude/.claude/commands/dare-ax.md +131 -131
- package/templates/ide/claude/.claude/commands/dare-bench.md +18 -18
- package/templates/ide/claude/.claude/commands/dare-blueprint.md +134 -134
- package/templates/ide/claude/.claude/commands/dare-bootstrap.md +27 -27
- package/templates/ide/claude/.claude/commands/dare-bugfix-design.md +119 -119
- package/templates/ide/claude/.claude/commands/dare-dag-build.md +151 -151
- package/templates/ide/claude/.claude/commands/dare-dag-run.md +109 -109
- package/templates/ide/claude/.claude/commands/dare-dag-runner.md +117 -117
- package/templates/ide/claude/.claude/commands/dare-dag-viz.md +197 -197
- package/templates/ide/claude/.claude/commands/dare-dag.md +27 -27
- package/templates/ide/claude/.claude/commands/dare-design.md +69 -69
- package/templates/ide/claude/.claude/commands/dare-discover.md +28 -28
- package/templates/ide/claude/.claude/commands/dare-dna.md +75 -75
- package/templates/ide/claude/.claude/commands/dare-docker.md +207 -207
- package/templates/ide/claude/.claude/commands/dare-execute.md +152 -152
- package/templates/ide/claude/.claude/commands/dare-feature-design.md +147 -147
- package/templates/ide/claude/.claude/commands/dare-frontend-design.md +149 -149
- package/templates/ide/claude/.claude/commands/dare-graph.md +30 -30
- package/templates/ide/claude/.claude/commands/dare-info.md +26 -26
- package/templates/ide/claude/.claude/commands/dare-init.md +30 -30
- package/templates/ide/claude/.claude/commands/dare-laravel-api.md +211 -211
- package/templates/ide/claude/.claude/commands/dare-layered-design.md +124 -124
- package/templates/ide/claude/.claude/commands/dare-llm-integration.md +148 -148
- package/templates/ide/claude/.claude/commands/dare-migrate.md +72 -72
- package/templates/ide/claude/.claude/commands/dare-quality-telemetry.md +166 -166
- package/templates/ide/claude/.claude/commands/dare-realtime.md +159 -159
- package/templates/ide/claude/.claude/commands/dare-refine.md +145 -145
- package/templates/ide/claude/.claude/commands/dare-reverse.md +139 -139
- package/templates/ide/claude/.claude/commands/dare-review.md +113 -113
- package/templates/ide/claude/.claude/commands/dare-rust-leptos.md +269 -269
- package/templates/ide/claude/.claude/commands/dare-rust-workspace.md +209 -209
- package/templates/ide/claude/.claude/commands/dare-security.md +232 -232
- package/templates/ide/claude/.claude/commands/dare-skill.md +30 -30
- package/templates/ide/claude/.claude/commands/dare-tasks.md +70 -70
- package/templates/ide/claude/.claude/commands/dare-telemetry.md +132 -132
- package/templates/ide/claude/.claude/commands/dare-update.md +28 -28
- package/templates/ide/claude/.claude/commands/dare-validate.md +28 -28
- package/templates/ide/claude/.claude/commands/dare-welcome.md +25 -25
- package/templates/ide/claude/.claude/commands/skill-fastapi-api.md +205 -205
- package/templates/ide/claude/.claude/commands/skill-go-gin-api.md +232 -232
- package/templates/ide/claude/.claude/commands/skill-mcp-server.md +228 -228
- package/templates/ide/claude/.claude/commands/skill-nestjs-api.md +210 -210
- package/templates/ide/claude/.claude/commands/skill-rails-api.md +236 -236
- package/templates/ide/claude/.claude/settings.example.json +35 -35
- package/templates/ide/claude/CLAUDE.md +146 -146
- package/templates/ide/claude/templates/BLUEPRINT-template.md +193 -193
- package/templates/ide/claude/templates/DESIGN-template.md +129 -129
- package/templates/ide/claude/templates/TASK-SPEC-template.md +141 -141
- package/templates/ide/claude/templates/TASKS-template.md +26 -26
- package/templates/ide/claude/templates/TELEMETRY-template.md +125 -125
- package/templates/ide/cursor/.cursor/commands/dare-bench.md +18 -18
- package/templates/ide/cursor/.cursor/commands/dare-blueprint.md +86 -86
- package/templates/ide/cursor/.cursor/commands/dare-bootstrap.md +27 -27
- package/templates/ide/cursor/.cursor/commands/dare-bugfix-design.md +64 -64
- package/templates/ide/cursor/.cursor/commands/dare-dag-run.md +110 -110
- package/templates/ide/cursor/.cursor/commands/dare-dag-viz.md +139 -139
- package/templates/ide/cursor/.cursor/commands/dare-dag.md +27 -27
- package/templates/ide/cursor/.cursor/commands/dare-design.md +35 -35
- package/templates/ide/cursor/.cursor/commands/dare-discover.md +28 -28
- package/templates/ide/cursor/.cursor/commands/dare-dna.md +75 -75
- package/templates/ide/cursor/.cursor/commands/dare-docker-compose.md +18 -18
- package/templates/ide/cursor/.cursor/commands/dare-dockerfile.md +17 -17
- package/templates/ide/cursor/.cursor/commands/dare-execute.md +19 -19
- package/templates/ide/cursor/.cursor/commands/dare-feature-design.md +64 -64
- package/templates/ide/cursor/.cursor/commands/dare-graph.md +30 -30
- package/templates/ide/cursor/.cursor/commands/dare-info.md +26 -26
- package/templates/ide/cursor/.cursor/commands/dare-init.md +30 -30
- package/templates/ide/cursor/.cursor/commands/dare-migrate.md +72 -72
- package/templates/ide/cursor/.cursor/commands/dare-refine.md +107 -107
- package/templates/ide/cursor/.cursor/commands/dare-reverse.md +139 -139
- package/templates/ide/cursor/.cursor/commands/dare-review.md +91 -91
- package/templates/ide/cursor/.cursor/commands/dare-skill.md +30 -30
- package/templates/ide/cursor/.cursor/commands/dare-tasks.md +184 -184
- package/templates/ide/cursor/.cursor/commands/dare-telemetry.md +42 -42
- package/templates/ide/cursor/.cursor/commands/dare-update.md +28 -28
- package/templates/ide/cursor/.cursor/commands/dare-validate.md +28 -28
- package/templates/ide/cursor/.cursor/commands/dare-welcome.md +25 -25
- package/templates/ide/cursor/.cursor/rules/skill-ax.mdc +263 -263
- package/templates/ide/cursor/.cursor/rules/skill-bugfix-design.mdc +51 -51
- package/templates/ide/cursor/.cursor/rules/skill-dag-build.mdc +173 -173
- package/templates/ide/cursor/.cursor/rules/skill-dag-run.mdc +134 -134
- package/templates/ide/cursor/.cursor/rules/skill-dag-runner.mdc +221 -221
- package/templates/ide/cursor/.cursor/rules/skill-dna.mdc +63 -63
- package/templates/ide/cursor/.cursor/rules/skill-docker.mdc +33 -33
- package/templates/ide/cursor/.cursor/rules/skill-fastapi-api.mdc +352 -352
- package/templates/ide/cursor/.cursor/rules/skill-feature-design.mdc +43 -43
- package/templates/ide/cursor/.cursor/rules/skill-frontend-design.mdc +244 -244
- package/templates/ide/cursor/.cursor/rules/skill-go-gin-api.mdc +371 -371
- package/templates/ide/cursor/.cursor/rules/skill-laravel-api.mdc +44 -44
- package/templates/ide/cursor/.cursor/rules/skill-layered-design.mdc +266 -266
- package/templates/ide/cursor/.cursor/rules/skill-llm-integration.mdc +295 -295
- package/templates/ide/cursor/.cursor/rules/skill-mcp-server.mdc +367 -367
- package/templates/ide/cursor/.cursor/rules/skill-migrate.mdc +58 -58
- package/templates/ide/cursor/.cursor/rules/skill-nestjs-api.mdc +346 -346
- package/templates/ide/cursor/.cursor/rules/skill-quality-telemetry.mdc +248 -248
- package/templates/ide/cursor/.cursor/rules/skill-rails-api.mdc +400 -400
- package/templates/ide/cursor/.cursor/rules/skill-realtime.mdc +262 -262
- package/templates/ide/cursor/.cursor/rules/skill-reverse.mdc +107 -107
- package/templates/ide/cursor/.cursor/rules/skill-rust-leptos.mdc +281 -281
- package/templates/ide/cursor/.cursor/rules/skill-rust-workspace.mdc +312 -312
- package/templates/ide/cursor/.cursor/rules/skill-security.mdc +245 -245
- package/templates/ide/cursor/.cursor/rules/skill-telemetry.mdc +156 -156
- package/templates/ide/cursor/templates/BLUEPRINT-template.md +193 -193
- package/templates/ide/cursor/templates/DESIGN-template.md +129 -129
- package/templates/ide/cursor/templates/TASK-SPEC-template.md +141 -141
- package/templates/ide/cursor/templates/TASKS-template.md +26 -26
- package/templates/ide/cursor/templates/TELEMETRY-template.md +125 -125
- package/templates/shared/docker-compose.yml +41 -41
- package/templates/stacks/go-gin/.dare/skills.yml +11 -11
- package/templates/stacks/go-gin/.env.example +24 -24
- package/templates/stacks/go-gin/.github/workflows/dare-ci.yml +42 -42
- package/templates/stacks/go-gin/README.md.tpl +38 -38
- package/templates/stacks/go-gin/cmd/server/main.go.tpl +78 -78
- package/templates/stacks/go-gin/db/migrations/0001_create_users.down.sql +2 -2
- package/templates/stacks/go-gin/db/migrations/0001_create_users.up.sql +12 -12
- package/templates/stacks/go-gin/db/queries/users.sql +23 -23
- package/templates/stacks/go-gin/gitignore +7 -7
- package/templates/stacks/go-gin/go.mod.tpl +17 -17
- package/templates/stacks/go-gin/internal/config/config.go +41 -41
- package/templates/stacks/go-gin/internal/db/postgres.go.tpl +25 -25
- package/templates/stacks/go-gin/internal/handler/auth_handler.go.tpl +72 -72
- package/templates/stacks/go-gin/internal/handler/users_handler.go.tpl +72 -72
- package/templates/stacks/go-gin/internal/handler/ws_handler.go +37 -37
- package/templates/stacks/go-gin/internal/llm/dummy.go +14 -14
- package/templates/stacks/go-gin/internal/llm/provider.go +8 -8
- package/templates/stacks/go-gin/internal/middleware/jwt.go.tpl +58 -58
- package/templates/stacks/go-gin/internal/middleware/rate_limit.go +55 -55
- package/templates/stacks/go-gin/internal/model/user.go +17 -17
- package/templates/stacks/go-gin/internal/repository/users_repository.go.tpl +79 -79
- package/templates/stacks/go-gin/internal/service/auth_service.go.tpl +55 -55
- package/templates/stacks/go-gin/internal/service/users_service.go.tpl +53 -53
- package/templates/stacks/go-gin/llms.txt.tpl +54 -54
- package/templates/stacks/go-gin/openapi.json.tpl +46 -46
- package/templates/stacks/go-gin/sqlc.yaml +14 -14
- package/templates/stacks/go-gin/tests/smoke_test.go.tpl +22 -22
- package/templates/stacks/go-stdlib/.dare/skills.yml +11 -11
- package/templates/stacks/go-stdlib/.env.example +24 -24
- package/templates/stacks/go-stdlib/.github/workflows/dare-ci.yml +42 -42
- package/templates/stacks/go-stdlib/README.md.tpl +41 -41
- package/templates/stacks/go-stdlib/cmd/server/main.go.tpl +82 -82
- package/templates/stacks/go-stdlib/db/migrations/0001_create_users.down.sql +2 -2
- package/templates/stacks/go-stdlib/db/migrations/0001_create_users.up.sql +12 -12
- package/templates/stacks/go-stdlib/db/queries/users.sql +23 -23
- package/templates/stacks/go-stdlib/gitignore +6 -6
- package/templates/stacks/go-stdlib/go.mod.tpl +15 -15
- package/templates/stacks/go-stdlib/internal/config/config.go +41 -41
- package/templates/stacks/go-stdlib/internal/db/postgres.go.tpl +24 -24
- package/templates/stacks/go-stdlib/internal/handler/auth_handler.go.tpl +71 -71
- package/templates/stacks/go-stdlib/internal/handler/users_handler.go.tpl +84 -84
- package/templates/stacks/go-stdlib/internal/handler/ws_handler.go +36 -36
- package/templates/stacks/go-stdlib/internal/httpx/json.go +32 -32
- package/templates/stacks/go-stdlib/internal/llm/dummy.go +14 -14
- package/templates/stacks/go-stdlib/internal/llm/provider.go +8 -8
- package/templates/stacks/go-stdlib/internal/middleware/chain.go +21 -21
- package/templates/stacks/go-stdlib/internal/middleware/cors.go +27 -27
- package/templates/stacks/go-stdlib/internal/middleware/jwt.go.tpl +51 -51
- package/templates/stacks/go-stdlib/internal/middleware/rate_limit.go +81 -81
- package/templates/stacks/go-stdlib/internal/model/user.go +17 -17
- package/templates/stacks/go-stdlib/internal/repository/users_repository.go.tpl +75 -75
- package/templates/stacks/go-stdlib/internal/service/auth_service.go.tpl +55 -55
- package/templates/stacks/go-stdlib/internal/service/users_service.go.tpl +53 -53
- package/templates/stacks/go-stdlib/llms.txt.tpl +60 -60
- package/templates/stacks/go-stdlib/openapi.json.tpl +46 -46
- package/templates/stacks/go-stdlib/sqlc.yaml +14 -14
- package/templates/stacks/go-stdlib/tests/smoke_test.go.tpl +45 -45
- package/templates/stacks/mcp-go/.dare/skills.yml +8 -8
- package/templates/stacks/mcp-go/.env.example +14 -14
- package/templates/stacks/mcp-go/.github/workflows/dare-ci.yml +42 -42
- package/templates/stacks/mcp-go/README.md.tpl +50 -50
- package/templates/stacks/mcp-go/cmd/server/main.go.tpl +62 -62
- package/templates/stacks/mcp-go/gitignore +6 -6
- package/templates/stacks/mcp-go/go.mod.tpl +9 -9
- package/templates/stacks/mcp-go/internal/prompts/summarize.go +9 -9
- package/templates/stacks/mcp-go/internal/server/server.go.tpl +80 -80
- package/templates/stacks/mcp-go/internal/tools/echo.go +15 -15
- package/templates/stacks/mcp-go/internal/transports/http.go.tpl +21 -21
- package/templates/stacks/mcp-go/internal/transports/sse.go.tpl +17 -17
- package/templates/stacks/mcp-go/internal/transports/stdio.go.tpl +14 -14
- package/templates/stacks/mcp-go/llms.txt.tpl +60 -60
- package/templates/stacks/mcp-go/openapi.json.tpl +31 -31
- package/templates/stacks/mcp-go/tests/echo_test.go.tpl +37 -37
- package/templates/stacks/mcp-node-ts/.dare/skills.yml +8 -8
- package/templates/stacks/mcp-node-ts/.env.example +16 -16
- package/templates/stacks/mcp-node-ts/.github/workflows/dare-ci.yml +54 -54
- package/templates/stacks/mcp-node-ts/README.md.hbs +49 -49
- package/templates/stacks/mcp-node-ts/gitignore +7 -7
- package/templates/stacks/mcp-node-ts/llms.txt.hbs +61 -61
- package/templates/stacks/mcp-node-ts/openapi.json.hbs +39 -39
- package/templates/stacks/mcp-node-ts/package.json.hbs +35 -35
- package/templates/stacks/mcp-node-ts/src/cli.ts.hbs +71 -71
- package/templates/stacks/mcp-node-ts/src/prompts/index.ts +36 -36
- package/templates/stacks/mcp-node-ts/src/server.ts.hbs +45 -45
- package/templates/stacks/mcp-node-ts/src/tools/echo.ts +23 -23
- package/templates/stacks/mcp-node-ts/src/tools/index.ts +18 -18
- package/templates/stacks/mcp-node-ts/src/transports/http.ts +68 -68
- package/templates/stacks/mcp-node-ts/src/transports/sse.ts +58 -58
- package/templates/stacks/mcp-node-ts/src/transports/stdio.ts +5 -5
- package/templates/stacks/mcp-node-ts/tests/echo.test.ts +50 -50
- package/templates/stacks/mcp-node-ts/tsconfig.json +17 -17
- package/templates/stacks/mcp-python/.dare/skills.yml +8 -8
- package/templates/stacks/mcp-python/.env.example +14 -14
- package/templates/stacks/mcp-python/.github/workflows/dare-ci.yml +42 -42
- package/templates/stacks/mcp-python/README.md.j2 +49 -49
- package/templates/stacks/mcp-python/gitignore +12 -12
- package/templates/stacks/mcp-python/llms.txt.j2 +56 -56
- package/templates/stacks/mcp-python/openapi.json.j2 +33 -33
- package/templates/stacks/mcp-python/pyproject.toml.j2 +37 -37
- package/templates/stacks/mcp-python/src/cli.py.j2 +68 -68
- package/templates/stacks/mcp-python/src/prompts/summarize.py +10 -10
- package/templates/stacks/mcp-python/src/server.py.j2 +28 -28
- package/templates/stacks/mcp-python/src/tools/echo.py +12 -12
- package/templates/stacks/mcp-python/src/transports/http.py +12 -12
- package/templates/stacks/mcp-python/src/transports/sse.py +13 -13
- package/templates/stacks/mcp-python/src/transports/stdio.py +6 -6
- package/templates/stacks/mcp-python/tests/test_echo.py +28 -28
- package/templates/stacks/mcp-rust/.dare/skills.yml +8 -8
- package/templates/stacks/mcp-rust/.env.example +14 -14
- package/templates/stacks/mcp-rust/.github/workflows/dare-ci.yml +38 -38
- package/templates/stacks/mcp-rust/Cargo.toml.tera +35 -35
- package/templates/stacks/mcp-rust/README.md.tera +50 -50
- package/templates/stacks/mcp-rust/gitignore +5 -5
- package/templates/stacks/mcp-rust/llms.txt.tera +60 -60
- package/templates/stacks/mcp-rust/openapi.json.tera +31 -31
- package/templates/stacks/mcp-rust/src/cli.rs.tera +33 -33
- package/templates/stacks/mcp-rust/src/lib.rs +6 -6
- package/templates/stacks/mcp-rust/src/main.rs.tera +30 -30
- package/templates/stacks/mcp-rust/src/prompts/mod.rs +1 -1
- package/templates/stacks/mcp-rust/src/prompts/summarize.rs +5 -5
- package/templates/stacks/mcp-rust/src/server.rs.tera +38 -38
- package/templates/stacks/mcp-rust/src/tools/echo.rs +18 -18
- package/templates/stacks/mcp-rust/src/tools/mod.rs +22 -22
- package/templates/stacks/mcp-rust/src/transports/http.rs +27 -27
- package/templates/stacks/mcp-rust/src/transports/mod.rs +3 -3
- package/templates/stacks/mcp-rust/src/transports/sse.rs +33 -33
- package/templates/stacks/mcp-rust/src/transports/stdio.rs +14 -14
- package/templates/stacks/mcp-rust/tests/echo_test.rs.tera +27 -27
- package/templates/stacks/node-nestjs/.dare/skills.yml +11 -11
- package/templates/stacks/node-nestjs/.env.example +21 -21
- package/templates/stacks/node-nestjs/.github/workflows/dare-ci.yml +54 -54
- package/templates/stacks/node-nestjs/README.md.hbs +35 -35
- package/templates/stacks/node-nestjs/gitignore +7 -7
- package/templates/stacks/node-nestjs/llms.txt.hbs +47 -47
- package/templates/stacks/node-nestjs/nest-cli.json +16 -16
- package/templates/stacks/node-nestjs/openapi.json.hbs +75 -75
- package/templates/stacks/node-nestjs/package.json.hbs +57 -57
- package/templates/stacks/node-nestjs/prisma/schema.prisma +25 -25
- package/templates/stacks/node-nestjs/prisma/seed.ts.hbs +25 -25
- package/templates/stacks/node-nestjs/src/app.module.ts +39 -39
- package/templates/stacks/node-nestjs/src/auth/auth.controller.ts +29 -29
- package/templates/stacks/node-nestjs/src/auth/auth.module.ts +25 -25
- package/templates/stacks/node-nestjs/src/auth/auth.service.ts +36 -36
- package/templates/stacks/node-nestjs/src/auth/dto/login-response.dto.ts +9 -9
- package/templates/stacks/node-nestjs/src/auth/dto/login.dto.ts +17 -17
- package/templates/stacks/node-nestjs/src/auth/jwt.strategy.ts +25 -25
- package/templates/stacks/node-nestjs/src/common/filters/problem-details.filter.ts +38 -38
- package/templates/stacks/node-nestjs/src/common/interceptors/json-response.interceptor.ts +13 -13
- package/templates/stacks/node-nestjs/src/main.ts.hbs +44 -44
- package/templates/stacks/node-nestjs/src/prisma/prisma.module.ts +9 -9
- package/templates/stacks/node-nestjs/src/prisma/prisma.service.ts +9 -9
- package/templates/stacks/node-nestjs/src/users/dto/create-user.dto.ts +22 -22
- package/templates/stacks/node-nestjs/src/users/dto/user.dto.ts +15 -15
- package/templates/stacks/node-nestjs/src/users/users.controller.ts +41 -41
- package/templates/stacks/node-nestjs/src/users/users.module.ts +11 -11
- package/templates/stacks/node-nestjs/src/users/users.repository.ts +38 -38
- package/templates/stacks/node-nestjs/src/users/users.service.ts +38 -38
- package/templates/stacks/node-nestjs/tsconfig.build.json +4 -4
- package/templates/stacks/node-nestjs/tsconfig.json +28 -28
- package/templates/stacks/php-laravel/.dare/skills.yml +11 -11
- package/templates/stacks/php-laravel/.env.example +41 -41
- package/templates/stacks/php-laravel/.github/workflows/dare-ci.yml +43 -43
- package/templates/stacks/php-laravel/README.md.hbs +36 -36
- package/templates/stacks/php-laravel/app/Http/Controllers/Api/AuthController.php +36 -36
- package/templates/stacks/php-laravel/app/Http/Controllers/Api/UsersController.php +33 -33
- package/templates/stacks/php-laravel/app/Http/Requests/CreateUserRequest.php +26 -26
- package/templates/stacks/php-laravel/app/Http/Requests/LoginRequest.php +34 -34
- package/templates/stacks/php-laravel/app/Llm/Contracts/LlmProvider.php +12 -12
- package/templates/stacks/php-laravel/app/Llm/Providers/DummyProvider.php +13 -13
- package/templates/stacks/php-laravel/app/Llm/Providers/OpenAiProvider.php +33 -33
- package/templates/stacks/php-laravel/app/Models/User.php +44 -44
- package/templates/stacks/php-laravel/app/Repositories/UsersRepository.php +32 -32
- package/templates/stacks/php-laravel/app/Services/AuthService.php +37 -37
- package/templates/stacks/php-laravel/app/Services/UsersService.php +57 -57
- package/templates/stacks/php-laravel/artisan +12 -12
- package/templates/stacks/php-laravel/bootstrap/app.php +29 -29
- package/templates/stacks/php-laravel/bootstrap/providers.php +5 -5
- package/templates/stacks/php-laravel/composer.json.hbs +58 -58
- package/templates/stacks/php-laravel/config/l5-swagger.php +41 -41
- package/templates/stacks/php-laravel/config/reverb.php +34 -34
- package/templates/stacks/php-laravel/config/sanctum.php +15 -15
- package/templates/stacks/php-laravel/database/migrations/2026_06_01_000001_create_users_table.php +27 -27
- package/templates/stacks/php-laravel/database/seeders/DatabaseSeeder.php +21 -21
- package/templates/stacks/php-laravel/gitignore +23 -23
- package/templates/stacks/php-laravel/llms.txt.hbs +53 -53
- package/templates/stacks/php-laravel/openapi.json.hbs +43 -43
- package/templates/stacks/php-laravel/phpstan.neon +9 -9
- package/templates/stacks/php-laravel/routes/api.php +13 -13
- package/templates/stacks/php-laravel/routes/channels.php +7 -7
- package/templates/stacks/php-laravel/tests/Feature/AuthTest.php +35 -35
- package/templates/stacks/php-laravel/tests/Feature/UsersTest.php +30 -30
- package/templates/stacks/php-laravel/tests/Pest.php +5 -5
- package/templates/stacks/python-fastapi/.dare/skills.yml +11 -11
- package/templates/stacks/python-fastapi/.env.example +21 -21
- package/templates/stacks/python-fastapi/.github/workflows/dare-ci.yml +43 -43
- package/templates/stacks/python-fastapi/README.md.j2 +35 -35
- package/templates/stacks/python-fastapi/alembic/env.py +46 -46
- package/templates/stacks/python-fastapi/alembic/script.py.mako +26 -26
- package/templates/stacks/python-fastapi/alembic/versions/0001_create_users.py.j2 +37 -37
- package/templates/stacks/python-fastapi/alembic.ini.j2 +39 -39
- package/templates/stacks/python-fastapi/app/core/config.py +24 -24
- package/templates/stacks/python-fastapi/app/core/security.py +34 -34
- package/templates/stacks/python-fastapi/app/db/session.py +22 -22
- package/templates/stacks/python-fastapi/app/main.py.j2 +36 -36
- package/templates/stacks/python-fastapi/app/models/__init__.py +3 -3
- package/templates/stacks/python-fastapi/app/models/user.py +30 -30
- package/templates/stacks/python-fastapi/app/repositories/user_repository.py +34 -34
- package/templates/stacks/python-fastapi/app/routers/auth.py +37 -37
- package/templates/stacks/python-fastapi/app/routers/users.py +46 -46
- package/templates/stacks/python-fastapi/app/schemas/user.py +56 -56
- package/templates/stacks/python-fastapi/app/services/auth_service.py +22 -22
- package/templates/stacks/python-fastapi/app/services/user_service.py +31 -31
- package/templates/stacks/python-fastapi/gitignore +12 -12
- package/templates/stacks/python-fastapi/llms.txt.j2 +53 -53
- package/templates/stacks/python-fastapi/openapi.json.j2 +43 -43
- package/templates/stacks/python-fastapi/pyproject.toml.j2 +45 -45
- package/templates/stacks/python-fastapi/tests/test_auth.py +22 -22
- package/templates/stacks/ruby-rails-8/.dare/skills.yml +50 -50
- package/templates/stacks/ruby-rails-8/.env.example +20 -20
- package/templates/stacks/ruby-rails-8/.github/workflows/dare-ci.yml +112 -112
- package/templates/stacks/ruby-rails-8/Gemfile.erb +61 -61
- package/templates/stacks/ruby-rails-8/app/channels/application_cable/channel.rb +11 -11
- package/templates/stacks/ruby-rails-8/app/channels/application_cable/connection.rb +34 -34
- package/templates/stacks/ruby-rails-8/app/channels/dare_updates_channel.rb +18 -18
- package/templates/stacks/ruby-rails-8/app/channels/user_updates_channel.rb +23 -23
- package/templates/stacks/ruby-rails-8/app/controllers/application_controller.rb +44 -44
- package/templates/stacks/ruby-rails-8/app/controllers/concerns/problem_details.rb +93 -93
- package/templates/stacks/ruby-rails-8/app/handlers/summarize_handler.rb +33 -33
- package/templates/stacks/ruby-rails-8/app/handlers/users_handler.rb +68 -68
- package/templates/stacks/ruby-rails-8/app/llm/cache/llm_cache.rb +44 -44
- package/templates/stacks/ruby-rails-8/app/llm/prompts/prompt_loader.rb +54 -54
- package/templates/stacks/ruby-rails-8/app/llm/prompts/summarize_v1.jinja2 +12 -12
- package/templates/stacks/ruby-rails-8/app/llm/providers/dummy_provider.rb +35 -35
- package/templates/stacks/ruby-rails-8/app/llm/providers/llm_provider.rb +67 -67
- package/templates/stacks/ruby-rails-8/app/llm/providers/openai_provider.rb +62 -62
- package/templates/stacks/ruby-rails-8/app/llm/rate_limit/token_bucket.rb +82 -82
- package/templates/stacks/ruby-rails-8/app/llm/validators/summarize_output_schema.json +21 -21
- package/templates/stacks/ruby-rails-8/app/llm/validators/validator.rb +52 -52
- package/templates/stacks/ruby-rails-8/app/models/user.rb +36 -36
- package/templates/stacks/ruby-rails-8/app/presenters/user_presenter.rb +48 -48
- package/templates/stacks/ruby-rails-8/app/repositories/document_repository.rb +57 -57
- package/templates/stacks/ruby-rails-8/app/repositories/user_repository.rb +73 -73
- package/templates/stacks/ruby-rails-8/app/services/create_user_service.rb +67 -67
- package/templates/stacks/ruby-rails-8/app/services/realtime_service.rb +53 -53
- package/templates/stacks/ruby-rails-8/app/services/summarize_document_service.rb +57 -57
- package/templates/stacks/ruby-rails-8/config/dare.yml +42 -42
- package/templates/stacks/ruby-rails-8/config/initializers/dare.rb +31 -31
- package/templates/stacks/ruby-rails-8/config/initializers/rack_attack.rb +64 -64
- package/templates/stacks/ruby-rails-8/config/initializers/rswag_api.rb +12 -12
- package/templates/stacks/ruby-rails-8/lib/tasks/dare.rake +159 -159
- package/templates/stacks/ruby-rails-8/llms.txt.erb +69 -69
- package/templates/stacks/ruby-rails-8/spec/api/summarize_spec.rb +56 -56
- package/templates/stacks/ruby-rails-8/spec/api/users_spec.rb +72 -72
- package/templates/stacks/ruby-rails-8/spec/channels/dare_updates_channel_spec.rb +61 -61
- package/templates/stacks/ruby-rails-8/spec/channels/user_updates_channel_spec.rb +56 -56
- package/templates/stacks/ruby-rails-8/spec/factories/users.rb +27 -27
- package/templates/stacks/ruby-rails-8/spec/handlers/users_handler_spec.rb +88 -88
- package/templates/stacks/ruby-rails-8/spec/rails_helper.rb +31 -31
- package/templates/stacks/ruby-rails-8/spec/services/create_user_service_spec.rb +88 -88
- package/templates/stacks/ruby-rails-8/spec/services/summarize_document_service_spec.rb +142 -142
- package/templates/stacks/ruby-rails-8/spec/swagger_helper.rb +73 -73
- package/templates/stacks/rust-axum/.dare/skills.yml +11 -11
- package/templates/stacks/rust-axum/.env.example +26 -26
- package/templates/stacks/rust-axum/.github/workflows/dare-ci.yml +40 -40
- package/templates/stacks/rust-axum/Cargo.toml.tera +53 -53
- package/templates/stacks/rust-axum/README.md.tera +37 -37
- package/templates/stacks/rust-axum/gitignore +5 -5
- package/templates/stacks/rust-axum/llms.txt.tera +54 -54
- package/templates/stacks/rust-axum/migrations/0001_create_users.sql +13 -13
- package/templates/stacks/rust-axum/openapi.json.tera +46 -46
- package/templates/stacks/rust-axum/src/config.rs +45 -45
- package/templates/stacks/rust-axum/src/errors.rs +48 -48
- package/templates/stacks/rust-axum/src/handlers/auth.rs +48 -48
- package/templates/stacks/rust-axum/src/handlers/mod.rs +3 -3
- package/templates/stacks/rust-axum/src/handlers/users.rs +81 -81
- package/templates/stacks/rust-axum/src/handlers/ws.rs +24 -24
- package/templates/stacks/rust-axum/src/lib.rs +19 -19
- package/templates/stacks/rust-axum/src/llm/mod.rs +1 -1
- package/templates/stacks/rust-axum/src/llm/provider.rs +48 -48
- package/templates/stacks/rust-axum/src/main.rs.tera +64 -64
- package/templates/stacks/rust-axum/src/middleware/auth.rs +20 -20
- package/templates/stacks/rust-axum/src/middleware/mod.rs +2 -2
- package/templates/stacks/rust-axum/src/middleware/rate_limit.rs +27 -27
- package/templates/stacks/rust-axum/src/models/mod.rs +1 -1
- package/templates/stacks/rust-axum/src/models/user.rs +13 -13
- package/templates/stacks/rust-axum/src/repositories/mod.rs +1 -1
- package/templates/stacks/rust-axum/src/repositories/user_repository.rs +62 -62
- package/templates/stacks/rust-axum/src/services/auth_service.rs +50 -50
- package/templates/stacks/rust-axum/src/services/mod.rs +2 -2
- package/templates/stacks/rust-axum/src/services/user_service.rs +53 -53
- package/templates/stacks/rust-axum/tests/integration_test.rs.tera +13 -13
- package/dist/commands/new.d.ts +0 -16
- package/dist/commands/new.d.ts.map +0 -1
- package/dist/commands/new.js +0 -104
- package/dist/commands/new.js.map +0 -1
|
@@ -1,211 +1,211 @@
|
|
|
1
|
-
# /dare-laravel-api
|
|
2
|
-
|
|
3
|
-
Padrões DARE para APIs REST em Laravel 11 + PHP 8.3. Strict Types, FormRequests, Services, Resources, Repositories, Eloquent + casts, tratamento global de exceções, testes Pest, PHPStan/Larastan nível 8.
|
|
4
|
-
|
|
5
|
-
## Como usar
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
/dare-laravel-api # audita projeto Laravel
|
|
9
|
-
/dare-laravel-api scaffold users # gera CRUD com camadas
|
|
10
|
-
/dare-laravel-api migrate-controllers # extrai lógica de Controllers para Services
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Stack canônica
|
|
14
|
-
|
|
15
|
-
- PHP 8.3 com `declare(strict_types=1);` em todo arquivo
|
|
16
|
-
- Laravel 11.x modo API
|
|
17
|
-
- PostgreSQL 16 ou MySQL 8
|
|
18
|
-
- Pest para testes (ou PHPUnit 11)
|
|
19
|
-
- PHPStan + Larastan nível 8
|
|
20
|
-
- Pint para formatação
|
|
21
|
-
- Sanctum para auth
|
|
22
|
-
|
|
23
|
-
## Layered Design
|
|
24
|
-
|
|
25
|
-
| Camada | Pasta Laravel |
|
|
26
|
-
|---|---|
|
|
27
|
-
| Handler | `app/Http/Controllers/` |
|
|
28
|
-
| Service | `app/Services/` |
|
|
29
|
-
| Repository | `app/Repositories/` |
|
|
30
|
-
| Model | `app/Models/` |
|
|
31
|
-
| Presenter | `app/Http/Resources/` |
|
|
32
|
-
|
|
33
|
-
## Controllers (Handler)
|
|
34
|
-
|
|
35
|
-
```php
|
|
36
|
-
<?php declare(strict_types=1);
|
|
37
|
-
|
|
38
|
-
namespace App\Http\Controllers;
|
|
39
|
-
|
|
40
|
-
use App\Http\Requests\StoreUserRequest;
|
|
41
|
-
use App\Http\Resources\UserResource;
|
|
42
|
-
use App\Services\RegisterUser;
|
|
43
|
-
|
|
44
|
-
final class UserApiController extends Controller
|
|
45
|
-
{
|
|
46
|
-
public function __construct(private RegisterUser $service) {}
|
|
47
|
-
|
|
48
|
-
public function store(StoreUserRequest $request): UserResource
|
|
49
|
-
{
|
|
50
|
-
$user = $this->service->execute($request->validated());
|
|
51
|
-
return new UserResource($user);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
Regras:
|
|
57
|
-
- Apenas: recebe → valida via FormRequest → chama Service → retorna Resource
|
|
58
|
-
- NUNCA: query Eloquent, lógica de negócio, validação inline
|
|
59
|
-
|
|
60
|
-
## FormRequests
|
|
61
|
-
|
|
62
|
-
```php
|
|
63
|
-
final class StoreUserRequest extends FormRequest
|
|
64
|
-
{
|
|
65
|
-
public function authorize(): bool { return $this->user()->can('create', User::class); }
|
|
66
|
-
|
|
67
|
-
public function rules(): array {
|
|
68
|
-
return [
|
|
69
|
-
'email' => ['required', 'email', 'unique:users,email'],
|
|
70
|
-
'password' => ['required', 'string', 'min:12'],
|
|
71
|
-
];
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## Services
|
|
77
|
-
|
|
78
|
-
Uma operação por classe:
|
|
79
|
-
|
|
80
|
-
```php
|
|
81
|
-
final class RegisterUser
|
|
82
|
-
{
|
|
83
|
-
public function __construct(private UserRepository $users) {}
|
|
84
|
-
|
|
85
|
-
public function execute(array $data): User
|
|
86
|
-
{
|
|
87
|
-
if ($this->users->existsByEmail($data['email'])) {
|
|
88
|
-
throw new UserAlreadyExistsException();
|
|
89
|
-
}
|
|
90
|
-
return $this->users->create([...$data, 'password' => Hash::make($data['password'])]);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
## Repositories
|
|
96
|
-
|
|
97
|
-
```php
|
|
98
|
-
final class UserRepository
|
|
99
|
-
{
|
|
100
|
-
public function existsByEmail(string $email): bool {
|
|
101
|
-
return User::where('email', $email)->exists();
|
|
102
|
-
}
|
|
103
|
-
public function create(array $data): User {
|
|
104
|
-
return User::create($data);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## Resources
|
|
110
|
-
|
|
111
|
-
Nunca retorne Model direto:
|
|
112
|
-
|
|
113
|
-
```php
|
|
114
|
-
final class UserResource extends JsonResource
|
|
115
|
-
{
|
|
116
|
-
public function toArray($request): array {
|
|
117
|
-
return [
|
|
118
|
-
'id' => $this->id,
|
|
119
|
-
'email' => $this->email,
|
|
120
|
-
'createdAt' => $this->created_at?->toIso8601String(),
|
|
121
|
-
];
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
## Exceções globais (`bootstrap/app.php`)
|
|
127
|
-
|
|
128
|
-
```php
|
|
129
|
-
->withExceptions(function (Exceptions $exceptions) {
|
|
130
|
-
$exceptions->render(fn (UserAlreadyExistsException $e) =>
|
|
131
|
-
response()->json(['error' => 'User exists', 'code' => 'USER_EXISTS'], 409));
|
|
132
|
-
})
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
## Transações
|
|
136
|
-
|
|
137
|
-
```php
|
|
138
|
-
DB::transaction(function () use ($data) {
|
|
139
|
-
$user = User::create($data);
|
|
140
|
-
UserProfile::create([...]);
|
|
141
|
-
});
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
## Testes Pest
|
|
145
|
-
|
|
146
|
-
```php
|
|
147
|
-
it('cria usuário com sucesso', function () {
|
|
148
|
-
$this->actingAs(User::factory()->admin()->create())
|
|
149
|
-
->postJson('/api/users', ['email' => 'jane@example.com', 'name' => 'Jane', 'password' => 'longsecret123'])
|
|
150
|
-
->assertCreated();
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it('rejeita email duplicado', function () {
|
|
154
|
-
User::factory()->create(['email' => 'taken@example.com']);
|
|
155
|
-
$this->actingAs(User::factory()->admin()->create())
|
|
156
|
-
->postJson('/api/users', ['email' => 'taken@example.com', ...])
|
|
157
|
-
->assertStatus(409);
|
|
158
|
-
});
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
Cobertura mínima por endpoint: 200/201, 422, 401/403, 404.
|
|
162
|
-
|
|
163
|
-
## Antipatterns
|
|
164
|
-
|
|
165
|
-
| AP | Antipattern | Correção |
|
|
166
|
-
|---|---|---|
|
|
167
|
-
| AP-01 | `$request->validate()` no Controller | FormRequest |
|
|
168
|
-
| AP-02 | Query Eloquent no Controller | Repository |
|
|
169
|
-
| AP-03 | Lógica no Controller | Service |
|
|
170
|
-
| AP-04 | Retornar Model direto | JsonResource |
|
|
171
|
-
| AP-05 | `$guarded = []` | `$fillable` explícito |
|
|
172
|
-
| AP-06 | Sem `declare(strict_types=1)` | Adicionar no topo |
|
|
173
|
-
| AP-07 | Múltiplas inserções sem transaction | `DB::transaction()` |
|
|
174
|
-
| AP-08 | `bcrypt()` default cost | `Hash::make($pwd, ['rounds' => 12])` |
|
|
175
|
-
|
|
176
|
-
## Validação no CI
|
|
177
|
-
|
|
178
|
-
```bash
|
|
179
|
-
./vendor/bin/phpstan analyse --level=8
|
|
180
|
-
./vendor/bin/pint --test
|
|
181
|
-
./vendor/bin/pest --coverage --min=80
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
## O que fazer
|
|
185
|
-
|
|
186
|
-
1. Audit:
|
|
187
|
-
```bash
|
|
188
|
-
grep -rn "request()->validate" app/Http/Controllers/
|
|
189
|
-
grep -rn "::where\|::find" app/Http/Controllers/
|
|
190
|
-
./vendor/bin/phpstan analyse --level=8
|
|
191
|
-
```
|
|
192
|
-
2. Para cada `$request->validate(...)` → FormRequest com `php artisan make:request`
|
|
193
|
-
3. Para cada Controller com lógica > 10 linhas → Service
|
|
194
|
-
4. Para cada query Eloquent em Controller → Repository
|
|
195
|
-
5. Substituir `return $user` por `return new UserResource($user)`
|
|
196
|
-
6. Adicionar `declare(strict_types=1);` em todo arquivo
|
|
197
|
-
|
|
198
|
-
## Segurança (combinar com `/dare-security`)
|
|
199
|
-
|
|
200
|
-
- Hash com `Hash::make($pwd, ['rounds' => 12])` ou Argon2
|
|
201
|
-
- Sanctum para SPA/mobile
|
|
202
|
-
- `ThrottleRequests` middleware
|
|
203
|
-
- Headers de segurança (HSTS, X-Frame, CSP) em middleware
|
|
204
|
-
- CORS específico, nunca `*` em produção
|
|
205
|
-
- `$fillable` SEMPRE, nunca `$guarded = []`
|
|
206
|
-
|
|
207
|
-
$ARGUMENTS
|
|
208
|
-
|
|
209
|
-
---
|
|
210
|
-
|
|
211
|
-
Skill MIT — parte do DARE Method.
|
|
1
|
+
# /dare-laravel-api
|
|
2
|
+
|
|
3
|
+
Padrões DARE para APIs REST em Laravel 11 + PHP 8.3. Strict Types, FormRequests, Services, Resources, Repositories, Eloquent + casts, tratamento global de exceções, testes Pest, PHPStan/Larastan nível 8.
|
|
4
|
+
|
|
5
|
+
## Como usar
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/dare-laravel-api # audita projeto Laravel
|
|
9
|
+
/dare-laravel-api scaffold users # gera CRUD com camadas
|
|
10
|
+
/dare-laravel-api migrate-controllers # extrai lógica de Controllers para Services
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Stack canônica
|
|
14
|
+
|
|
15
|
+
- PHP 8.3 com `declare(strict_types=1);` em todo arquivo
|
|
16
|
+
- Laravel 11.x modo API
|
|
17
|
+
- PostgreSQL 16 ou MySQL 8
|
|
18
|
+
- Pest para testes (ou PHPUnit 11)
|
|
19
|
+
- PHPStan + Larastan nível 8
|
|
20
|
+
- Pint para formatação
|
|
21
|
+
- Sanctum para auth
|
|
22
|
+
|
|
23
|
+
## Layered Design
|
|
24
|
+
|
|
25
|
+
| Camada | Pasta Laravel |
|
|
26
|
+
|---|---|
|
|
27
|
+
| Handler | `app/Http/Controllers/` |
|
|
28
|
+
| Service | `app/Services/` |
|
|
29
|
+
| Repository | `app/Repositories/` |
|
|
30
|
+
| Model | `app/Models/` |
|
|
31
|
+
| Presenter | `app/Http/Resources/` |
|
|
32
|
+
|
|
33
|
+
## Controllers (Handler)
|
|
34
|
+
|
|
35
|
+
```php
|
|
36
|
+
<?php declare(strict_types=1);
|
|
37
|
+
|
|
38
|
+
namespace App\Http\Controllers;
|
|
39
|
+
|
|
40
|
+
use App\Http\Requests\StoreUserRequest;
|
|
41
|
+
use App\Http\Resources\UserResource;
|
|
42
|
+
use App\Services\RegisterUser;
|
|
43
|
+
|
|
44
|
+
final class UserApiController extends Controller
|
|
45
|
+
{
|
|
46
|
+
public function __construct(private RegisterUser $service) {}
|
|
47
|
+
|
|
48
|
+
public function store(StoreUserRequest $request): UserResource
|
|
49
|
+
{
|
|
50
|
+
$user = $this->service->execute($request->validated());
|
|
51
|
+
return new UserResource($user);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Regras:
|
|
57
|
+
- Apenas: recebe → valida via FormRequest → chama Service → retorna Resource
|
|
58
|
+
- NUNCA: query Eloquent, lógica de negócio, validação inline
|
|
59
|
+
|
|
60
|
+
## FormRequests
|
|
61
|
+
|
|
62
|
+
```php
|
|
63
|
+
final class StoreUserRequest extends FormRequest
|
|
64
|
+
{
|
|
65
|
+
public function authorize(): bool { return $this->user()->can('create', User::class); }
|
|
66
|
+
|
|
67
|
+
public function rules(): array {
|
|
68
|
+
return [
|
|
69
|
+
'email' => ['required', 'email', 'unique:users,email'],
|
|
70
|
+
'password' => ['required', 'string', 'min:12'],
|
|
71
|
+
];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Services
|
|
77
|
+
|
|
78
|
+
Uma operação por classe:
|
|
79
|
+
|
|
80
|
+
```php
|
|
81
|
+
final class RegisterUser
|
|
82
|
+
{
|
|
83
|
+
public function __construct(private UserRepository $users) {}
|
|
84
|
+
|
|
85
|
+
public function execute(array $data): User
|
|
86
|
+
{
|
|
87
|
+
if ($this->users->existsByEmail($data['email'])) {
|
|
88
|
+
throw new UserAlreadyExistsException();
|
|
89
|
+
}
|
|
90
|
+
return $this->users->create([...$data, 'password' => Hash::make($data['password'])]);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Repositories
|
|
96
|
+
|
|
97
|
+
```php
|
|
98
|
+
final class UserRepository
|
|
99
|
+
{
|
|
100
|
+
public function existsByEmail(string $email): bool {
|
|
101
|
+
return User::where('email', $email)->exists();
|
|
102
|
+
}
|
|
103
|
+
public function create(array $data): User {
|
|
104
|
+
return User::create($data);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Resources
|
|
110
|
+
|
|
111
|
+
Nunca retorne Model direto:
|
|
112
|
+
|
|
113
|
+
```php
|
|
114
|
+
final class UserResource extends JsonResource
|
|
115
|
+
{
|
|
116
|
+
public function toArray($request): array {
|
|
117
|
+
return [
|
|
118
|
+
'id' => $this->id,
|
|
119
|
+
'email' => $this->email,
|
|
120
|
+
'createdAt' => $this->created_at?->toIso8601String(),
|
|
121
|
+
];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Exceções globais (`bootstrap/app.php`)
|
|
127
|
+
|
|
128
|
+
```php
|
|
129
|
+
->withExceptions(function (Exceptions $exceptions) {
|
|
130
|
+
$exceptions->render(fn (UserAlreadyExistsException $e) =>
|
|
131
|
+
response()->json(['error' => 'User exists', 'code' => 'USER_EXISTS'], 409));
|
|
132
|
+
})
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Transações
|
|
136
|
+
|
|
137
|
+
```php
|
|
138
|
+
DB::transaction(function () use ($data) {
|
|
139
|
+
$user = User::create($data);
|
|
140
|
+
UserProfile::create([...]);
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Testes Pest
|
|
145
|
+
|
|
146
|
+
```php
|
|
147
|
+
it('cria usuário com sucesso', function () {
|
|
148
|
+
$this->actingAs(User::factory()->admin()->create())
|
|
149
|
+
->postJson('/api/users', ['email' => 'jane@example.com', 'name' => 'Jane', 'password' => 'longsecret123'])
|
|
150
|
+
->assertCreated();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('rejeita email duplicado', function () {
|
|
154
|
+
User::factory()->create(['email' => 'taken@example.com']);
|
|
155
|
+
$this->actingAs(User::factory()->admin()->create())
|
|
156
|
+
->postJson('/api/users', ['email' => 'taken@example.com', ...])
|
|
157
|
+
->assertStatus(409);
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Cobertura mínima por endpoint: 200/201, 422, 401/403, 404.
|
|
162
|
+
|
|
163
|
+
## Antipatterns
|
|
164
|
+
|
|
165
|
+
| AP | Antipattern | Correção |
|
|
166
|
+
|---|---|---|
|
|
167
|
+
| AP-01 | `$request->validate()` no Controller | FormRequest |
|
|
168
|
+
| AP-02 | Query Eloquent no Controller | Repository |
|
|
169
|
+
| AP-03 | Lógica no Controller | Service |
|
|
170
|
+
| AP-04 | Retornar Model direto | JsonResource |
|
|
171
|
+
| AP-05 | `$guarded = []` | `$fillable` explícito |
|
|
172
|
+
| AP-06 | Sem `declare(strict_types=1)` | Adicionar no topo |
|
|
173
|
+
| AP-07 | Múltiplas inserções sem transaction | `DB::transaction()` |
|
|
174
|
+
| AP-08 | `bcrypt()` default cost | `Hash::make($pwd, ['rounds' => 12])` |
|
|
175
|
+
|
|
176
|
+
## Validação no CI
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
./vendor/bin/phpstan analyse --level=8
|
|
180
|
+
./vendor/bin/pint --test
|
|
181
|
+
./vendor/bin/pest --coverage --min=80
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## O que fazer
|
|
185
|
+
|
|
186
|
+
1. Audit:
|
|
187
|
+
```bash
|
|
188
|
+
grep -rn "request()->validate" app/Http/Controllers/
|
|
189
|
+
grep -rn "::where\|::find" app/Http/Controllers/
|
|
190
|
+
./vendor/bin/phpstan analyse --level=8
|
|
191
|
+
```
|
|
192
|
+
2. Para cada `$request->validate(...)` → FormRequest com `php artisan make:request`
|
|
193
|
+
3. Para cada Controller com lógica > 10 linhas → Service
|
|
194
|
+
4. Para cada query Eloquent em Controller → Repository
|
|
195
|
+
5. Substituir `return $user` por `return new UserResource($user)`
|
|
196
|
+
6. Adicionar `declare(strict_types=1);` em todo arquivo
|
|
197
|
+
|
|
198
|
+
## Segurança (combinar com `/dare-security`)
|
|
199
|
+
|
|
200
|
+
- Hash com `Hash::make($pwd, ['rounds' => 12])` ou Argon2
|
|
201
|
+
- Sanctum para SPA/mobile
|
|
202
|
+
- `ThrottleRequests` middleware
|
|
203
|
+
- Headers de segurança (HSTS, X-Frame, CSP) em middleware
|
|
204
|
+
- CORS específico, nunca `*` em produção
|
|
205
|
+
- `$fillable` SEMPRE, nunca `$guarded = []`
|
|
206
|
+
|
|
207
|
+
$ARGUMENTS
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
Skill MIT — parte do DARE Method.
|
|
@@ -1,124 +1,124 @@
|
|
|
1
|
-
# /dare-layered-design
|
|
2
|
-
|
|
3
|
-
Enforce arquitetura estrita de 4 camadas (Handlers, Services, Repositories, Models) em projetos DARE — independente de linguagem.
|
|
4
|
-
|
|
5
|
-
## Como usar
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
/dare-layered-design # audita projeto atual
|
|
9
|
-
/dare-layered-design lint # roda checks AP-01 a AP-06
|
|
10
|
-
/dare-layered-design scaffold <recurso> # gera CRUD com camadas corretas
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## As 4 camadas
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
Handler → Service → Repository → Model
|
|
17
|
-
(HTTP) (negócio) (I/O) (domínio)
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
### Handler
|
|
21
|
-
- Recebe request, valida input, chama um Service, retorna response
|
|
22
|
-
- **Nunca** acessa Repository direto, **nunca** instancia Service com `new`
|
|
23
|
-
|
|
24
|
-
### Service
|
|
25
|
-
- Implementa uma operação de negócio (`RegisterUser`, `RefundPayment`)
|
|
26
|
-
- Orquestra Repositories
|
|
27
|
-
- **Nunca** sabe sobre HTTP, **nunca** faz SQL inline
|
|
28
|
-
|
|
29
|
-
### Repository
|
|
30
|
-
- Abstrai persistência (DB, cache, API externa)
|
|
31
|
-
- Retorna Model ou primitivo
|
|
32
|
-
- **Nunca** retorna HTTP status, **nunca** lança exceção de domínio
|
|
33
|
-
|
|
34
|
-
### Model
|
|
35
|
-
- Entidade pura do domínio
|
|
36
|
-
- **Nunca** importa Repository/Service/Handler
|
|
37
|
-
|
|
38
|
-
## Métricas obrigatórias
|
|
39
|
-
|
|
40
|
-
| ID | Métrica |
|
|
41
|
-
|---|---|
|
|
42
|
-
| M-01 | 100% dos Services têm testes unitários (sem DB/HTTP real) |
|
|
43
|
-
| M-02 | 0% de chamadas Handler→Repository direto |
|
|
44
|
-
| M-03 | 100% dos Handlers usam injeção (sem `new Service()`) |
|
|
45
|
-
| M-04 | 100% dos Repositories são agnósticos das camadas superiores |
|
|
46
|
-
|
|
47
|
-
## Tabela por linguagem
|
|
48
|
-
|
|
49
|
-
| Camada | Laravel | NestJS | FastAPI | Rails | Rust | Go |
|
|
50
|
-
|---|---|---|---|---|---|---|
|
|
51
|
-
| Handler | `Http/Controllers/` | `*.controller.ts` | `routers/` | `app/controllers/` | `handlers/` | `handlers/` |
|
|
52
|
-
| Service | `Services/` | `*.service.ts` | `services/` | `app/services/` | `services/` | `services/` |
|
|
53
|
-
| Repository | `Repositories/` | `*.repository.ts` | `repositories/` | `app/repositories/` | `repositories/` | `repositories/` |
|
|
54
|
-
| Model | `Models/` | `entities/` | `models/` | `app/models/` | `domain/` | `models/` |
|
|
55
|
-
|
|
56
|
-
## Antipatterns
|
|
57
|
-
|
|
58
|
-
| AP | Antipattern | Sinal |
|
|
59
|
-
|---|---|---|
|
|
60
|
-
| AP-01 | Handler→Repository direto | `controller.repo.find()` |
|
|
61
|
-
| AP-02 | Service com SQL inline | `db.query()` em Service |
|
|
62
|
-
| AP-03 | Repository lança exceção de domínio | `throw UserNotFound` |
|
|
63
|
-
| AP-04 | Model importa Service | acoplamento invertido |
|
|
64
|
-
| AP-05 | God Service (>20 métodos) | `UserService.everything()` |
|
|
65
|
-
| AP-06 | Fat Controller (>100 linhas) | lógica em Handler |
|
|
66
|
-
|
|
67
|
-
## O que fazer
|
|
68
|
-
|
|
69
|
-
### Passo 1: Mapear camadas existentes
|
|
70
|
-
|
|
71
|
-
Liste as pastas atuais e classifique cada uma como Handler, Service, Repository, Model ou "indefinido". Indefinido = candidato a refactor.
|
|
72
|
-
|
|
73
|
-
### Passo 2: Detectar violações com grep
|
|
74
|
-
|
|
75
|
-
```bash
|
|
76
|
-
# AP-01: Handler→Repository direto
|
|
77
|
-
grep -rn "Repository" src/controllers/ # Laravel/NestJS
|
|
78
|
-
grep -rn "Repository" app/controllers/ # Rails
|
|
79
|
-
|
|
80
|
-
# AP-02: SQL inline em Service
|
|
81
|
-
grep -rn "SELECT\\|INSERT\\|UPDATE\\|DELETE" src/services/
|
|
82
|
-
|
|
83
|
-
# AP-03: Exceção de domínio em Repository
|
|
84
|
-
grep -rn "throw.*NotFound\\|raise.*NotFound" src/repositories/
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### Passo 3: Quebrar God Service
|
|
88
|
-
|
|
89
|
-
Para cada Service com >20 métodos, separe em vários services nomeados por operação:
|
|
90
|
-
- `UserService.register()` → `RegisterUser`
|
|
91
|
-
- `UserService.resetPassword()` → `ResetPassword`
|
|
92
|
-
- `UserService.delete()` → `DeleteUser`
|
|
93
|
-
|
|
94
|
-
### Passo 4: Cobrir Services com testes unitários
|
|
95
|
-
|
|
96
|
-
Service não depende de DB nem HTTP real — Repository é mockado:
|
|
97
|
-
|
|
98
|
-
```typescript
|
|
99
|
-
const repo = { findByEmail: jest.fn().mockResolvedValue({id: 1}) };
|
|
100
|
-
const sut = new RegisterUserService(repo as any);
|
|
101
|
-
await expect(sut.execute(...)).rejects.toThrow();
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### Passo 5: Adicionar lint no CI
|
|
105
|
-
|
|
106
|
-
```yaml
|
|
107
|
-
- name: Layered design lint
|
|
108
|
-
run: |
|
|
109
|
-
grep -rn "Repository" src/controllers/ && exit 1 || true
|
|
110
|
-
grep -rn "new .*Service" src/controllers/ && exit 1 || true
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
## Saída esperada
|
|
114
|
-
|
|
115
|
-
Reporte numerado por antipattern (AP-01 a AP-06):
|
|
116
|
-
- Quantas violações por arquivo
|
|
117
|
-
- Sugestão concreta de refactor para cada uma
|
|
118
|
-
- Lista de Services sem cobertura unitária
|
|
119
|
-
|
|
120
|
-
$ARGUMENTS
|
|
121
|
-
|
|
122
|
-
---
|
|
123
|
-
|
|
124
|
-
Skill MIT — parte do DARE Method. Inspirado em "Layered Design for Ruby on Rails Applications" de Vladimir Dementyev (Evil Martians).
|
|
1
|
+
# /dare-layered-design
|
|
2
|
+
|
|
3
|
+
Enforce arquitetura estrita de 4 camadas (Handlers, Services, Repositories, Models) em projetos DARE — independente de linguagem.
|
|
4
|
+
|
|
5
|
+
## Como usar
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/dare-layered-design # audita projeto atual
|
|
9
|
+
/dare-layered-design lint # roda checks AP-01 a AP-06
|
|
10
|
+
/dare-layered-design scaffold <recurso> # gera CRUD com camadas corretas
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## As 4 camadas
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
Handler → Service → Repository → Model
|
|
17
|
+
(HTTP) (negócio) (I/O) (domínio)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Handler
|
|
21
|
+
- Recebe request, valida input, chama um Service, retorna response
|
|
22
|
+
- **Nunca** acessa Repository direto, **nunca** instancia Service com `new`
|
|
23
|
+
|
|
24
|
+
### Service
|
|
25
|
+
- Implementa uma operação de negócio (`RegisterUser`, `RefundPayment`)
|
|
26
|
+
- Orquestra Repositories
|
|
27
|
+
- **Nunca** sabe sobre HTTP, **nunca** faz SQL inline
|
|
28
|
+
|
|
29
|
+
### Repository
|
|
30
|
+
- Abstrai persistência (DB, cache, API externa)
|
|
31
|
+
- Retorna Model ou primitivo
|
|
32
|
+
- **Nunca** retorna HTTP status, **nunca** lança exceção de domínio
|
|
33
|
+
|
|
34
|
+
### Model
|
|
35
|
+
- Entidade pura do domínio
|
|
36
|
+
- **Nunca** importa Repository/Service/Handler
|
|
37
|
+
|
|
38
|
+
## Métricas obrigatórias
|
|
39
|
+
|
|
40
|
+
| ID | Métrica |
|
|
41
|
+
|---|---|
|
|
42
|
+
| M-01 | 100% dos Services têm testes unitários (sem DB/HTTP real) |
|
|
43
|
+
| M-02 | 0% de chamadas Handler→Repository direto |
|
|
44
|
+
| M-03 | 100% dos Handlers usam injeção (sem `new Service()`) |
|
|
45
|
+
| M-04 | 100% dos Repositories são agnósticos das camadas superiores |
|
|
46
|
+
|
|
47
|
+
## Tabela por linguagem
|
|
48
|
+
|
|
49
|
+
| Camada | Laravel | NestJS | FastAPI | Rails | Rust | Go |
|
|
50
|
+
|---|---|---|---|---|---|---|
|
|
51
|
+
| Handler | `Http/Controllers/` | `*.controller.ts` | `routers/` | `app/controllers/` | `handlers/` | `handlers/` |
|
|
52
|
+
| Service | `Services/` | `*.service.ts` | `services/` | `app/services/` | `services/` | `services/` |
|
|
53
|
+
| Repository | `Repositories/` | `*.repository.ts` | `repositories/` | `app/repositories/` | `repositories/` | `repositories/` |
|
|
54
|
+
| Model | `Models/` | `entities/` | `models/` | `app/models/` | `domain/` | `models/` |
|
|
55
|
+
|
|
56
|
+
## Antipatterns
|
|
57
|
+
|
|
58
|
+
| AP | Antipattern | Sinal |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| AP-01 | Handler→Repository direto | `controller.repo.find()` |
|
|
61
|
+
| AP-02 | Service com SQL inline | `db.query()` em Service |
|
|
62
|
+
| AP-03 | Repository lança exceção de domínio | `throw UserNotFound` |
|
|
63
|
+
| AP-04 | Model importa Service | acoplamento invertido |
|
|
64
|
+
| AP-05 | God Service (>20 métodos) | `UserService.everything()` |
|
|
65
|
+
| AP-06 | Fat Controller (>100 linhas) | lógica em Handler |
|
|
66
|
+
|
|
67
|
+
## O que fazer
|
|
68
|
+
|
|
69
|
+
### Passo 1: Mapear camadas existentes
|
|
70
|
+
|
|
71
|
+
Liste as pastas atuais e classifique cada uma como Handler, Service, Repository, Model ou "indefinido". Indefinido = candidato a refactor.
|
|
72
|
+
|
|
73
|
+
### Passo 2: Detectar violações com grep
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# AP-01: Handler→Repository direto
|
|
77
|
+
grep -rn "Repository" src/controllers/ # Laravel/NestJS
|
|
78
|
+
grep -rn "Repository" app/controllers/ # Rails
|
|
79
|
+
|
|
80
|
+
# AP-02: SQL inline em Service
|
|
81
|
+
grep -rn "SELECT\\|INSERT\\|UPDATE\\|DELETE" src/services/
|
|
82
|
+
|
|
83
|
+
# AP-03: Exceção de domínio em Repository
|
|
84
|
+
grep -rn "throw.*NotFound\\|raise.*NotFound" src/repositories/
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Passo 3: Quebrar God Service
|
|
88
|
+
|
|
89
|
+
Para cada Service com >20 métodos, separe em vários services nomeados por operação:
|
|
90
|
+
- `UserService.register()` → `RegisterUser`
|
|
91
|
+
- `UserService.resetPassword()` → `ResetPassword`
|
|
92
|
+
- `UserService.delete()` → `DeleteUser`
|
|
93
|
+
|
|
94
|
+
### Passo 4: Cobrir Services com testes unitários
|
|
95
|
+
|
|
96
|
+
Service não depende de DB nem HTTP real — Repository é mockado:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
const repo = { findByEmail: jest.fn().mockResolvedValue({id: 1}) };
|
|
100
|
+
const sut = new RegisterUserService(repo as any);
|
|
101
|
+
await expect(sut.execute(...)).rejects.toThrow();
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Passo 5: Adicionar lint no CI
|
|
105
|
+
|
|
106
|
+
```yaml
|
|
107
|
+
- name: Layered design lint
|
|
108
|
+
run: |
|
|
109
|
+
grep -rn "Repository" src/controllers/ && exit 1 || true
|
|
110
|
+
grep -rn "new .*Service" src/controllers/ && exit 1 || true
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Saída esperada
|
|
114
|
+
|
|
115
|
+
Reporte numerado por antipattern (AP-01 a AP-06):
|
|
116
|
+
- Quantas violações por arquivo
|
|
117
|
+
- Sugestão concreta de refactor para cada uma
|
|
118
|
+
- Lista de Services sem cobertura unitária
|
|
119
|
+
|
|
120
|
+
$ARGUMENTS
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
Skill MIT — parte do DARE Method. Inspirado em "Layered Design for Ruby on Rails Applications" de Vladimir Dementyev (Evil Martians).
|