@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,337 +1,337 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: dare-laravel-api
|
|
3
|
-
description: Padrões DARE para APIs REST em Laravel 11 + PHP 8.3 — Strict Types, FormRequests, Services, JsonResources, Eloquent + casts, tratamento global de exceções, testes Feature/Pest, PHPStan/Larastan, Pint.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# DARE Laravel API Skill
|
|
7
|
-
|
|
8
|
-
Você é um desenvolvedor sênior PHP 8.3 / Laravel 11.x especializado em APIs REST. Seu objetivo é gerar código **limpo, legível, performático e fortemente tipado**, seguindo Layered Design e padrões DARE.
|
|
9
|
-
|
|
10
|
-
## Quando usar
|
|
11
|
-
|
|
12
|
-
- Projeto Laravel novo via DARE
|
|
13
|
-
- Adicionar feature em API Laravel existente
|
|
14
|
-
- Auditar projeto Laravel para conformidade DARE
|
|
15
|
-
- Migrar API antiga (Laravel 8/9/10) para padrões 11.x
|
|
16
|
-
|
|
17
|
-
## Stack canônica
|
|
18
|
-
|
|
19
|
-
- **PHP 8.3** — Strict Types em todos os arquivos (`declare(strict_types=1);`)
|
|
20
|
-
- **Laravel 11.x** — modo API (sem views server-side por default)
|
|
21
|
-
- **Banco** — PostgreSQL (preferido) ou MySQL 8
|
|
22
|
-
- **Testes** — Pest (preferido) ou PHPUnit 11
|
|
23
|
-
- **Análise estática** — PHPStan + Larastan (nível 8)
|
|
24
|
-
- **Formatação** — Laravel Pint (`pint`)
|
|
25
|
-
- **Auth** — Laravel Sanctum (tokens) ou Passport (OAuth)
|
|
26
|
-
|
|
27
|
-
## Layered Design em Laravel
|
|
28
|
-
|
|
29
|
-
Mapeamento DARE → Laravel:
|
|
30
|
-
|
|
31
|
-
| Camada DARE | Pasta Laravel |
|
|
32
|
-
|---|---|
|
|
33
|
-
| Handler | `app/Http/Controllers/` |
|
|
34
|
-
| Service | `app/Services/` |
|
|
35
|
-
| Repository | `app/Repositories/` |
|
|
36
|
-
| Model | `app/Models/` |
|
|
37
|
-
| Presenter | `app/Http/Resources/` |
|
|
38
|
-
|
|
39
|
-
### Controllers (Handlers)
|
|
40
|
-
|
|
41
|
-
- Apenas: receber request → chamar Service → retornar Resource
|
|
42
|
-
- NUNCA: lógica de negócio, queries Eloquent, validação inline
|
|
43
|
-
|
|
44
|
-
```php
|
|
45
|
-
<?php declare(strict_types=1);
|
|
46
|
-
|
|
47
|
-
namespace App\Http\Controllers;
|
|
48
|
-
|
|
49
|
-
use App\Http\Requests\StoreUserRequest;
|
|
50
|
-
use App\Http\Resources\UserResource;
|
|
51
|
-
use App\Services\RegisterUser;
|
|
52
|
-
|
|
53
|
-
final class UserApiController extends Controller
|
|
54
|
-
{
|
|
55
|
-
public function __construct(private RegisterUser $service) {}
|
|
56
|
-
|
|
57
|
-
public function store(StoreUserRequest $request): UserResource
|
|
58
|
-
{
|
|
59
|
-
$user = $this->service->execute($request->validated());
|
|
60
|
-
return new UserResource($user);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### FormRequests (Validação)
|
|
66
|
-
|
|
67
|
-
NUNCA validar inline no Controller. Sempre FormRequest:
|
|
68
|
-
|
|
69
|
-
```php
|
|
70
|
-
<?php declare(strict_types=1);
|
|
71
|
-
|
|
72
|
-
namespace App\Http\Requests;
|
|
73
|
-
|
|
74
|
-
use Illuminate\Foundation\Http\FormRequest;
|
|
75
|
-
|
|
76
|
-
final class StoreUserRequest extends FormRequest
|
|
77
|
-
{
|
|
78
|
-
public function authorize(): bool
|
|
79
|
-
{
|
|
80
|
-
return $this->user()->can('create', User::class);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
public function rules(): array
|
|
84
|
-
{
|
|
85
|
-
return [
|
|
86
|
-
'email' => ['required', 'email', 'unique:users,email'],
|
|
87
|
-
'password' => ['required', 'string', 'min:12'],
|
|
88
|
-
'name' => ['required', 'string', 'max:255'],
|
|
89
|
-
];
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### Services (Business Logic)
|
|
95
|
-
|
|
96
|
-
Uma operação por classe. Strict types, exceções de domínio próprias.
|
|
97
|
-
|
|
98
|
-
```php
|
|
99
|
-
<?php declare(strict_types=1);
|
|
100
|
-
|
|
101
|
-
namespace App\Services;
|
|
102
|
-
|
|
103
|
-
use App\Exceptions\UserAlreadyExistsException;
|
|
104
|
-
use App\Models\User;
|
|
105
|
-
use App\Repositories\UserRepository;
|
|
106
|
-
use Illuminate\Support\Facades\Hash;
|
|
107
|
-
|
|
108
|
-
final class RegisterUser
|
|
109
|
-
{
|
|
110
|
-
public function __construct(private UserRepository $users) {}
|
|
111
|
-
|
|
112
|
-
public function execute(array $data): User
|
|
113
|
-
{
|
|
114
|
-
if ($this->users->existsByEmail($data['email'])) {
|
|
115
|
-
throw new UserAlreadyExistsException();
|
|
116
|
-
}
|
|
117
|
-
return $this->users->create([
|
|
118
|
-
'email' => $data['email'],
|
|
119
|
-
'name' => $data['name'],
|
|
120
|
-
'password' => Hash::make($data['password']),
|
|
121
|
-
]);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### Repositories (Data Access)
|
|
127
|
-
|
|
128
|
-
Abstrai Eloquent. Service só conhece o Repository, não o Model direto.
|
|
129
|
-
|
|
130
|
-
```php
|
|
131
|
-
<?php declare(strict_types=1);
|
|
132
|
-
|
|
133
|
-
namespace App\Repositories;
|
|
134
|
-
|
|
135
|
-
use App\Models\User;
|
|
136
|
-
|
|
137
|
-
final class UserRepository
|
|
138
|
-
{
|
|
139
|
-
public function existsByEmail(string $email): bool
|
|
140
|
-
{
|
|
141
|
-
return User::where('email', $email)->exists();
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
public function create(array $data): User
|
|
145
|
-
{
|
|
146
|
-
return User::create($data);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
### Resources (Presentation)
|
|
152
|
-
|
|
153
|
-
Nunca retorne Model direto do Controller. Sempre passe por JsonResource.
|
|
154
|
-
|
|
155
|
-
```php
|
|
156
|
-
<?php declare(strict_types=1);
|
|
157
|
-
|
|
158
|
-
namespace App\Http\Resources;
|
|
159
|
-
|
|
160
|
-
use Illuminate\Http\Resources\Json\JsonResource;
|
|
161
|
-
|
|
162
|
-
final class UserResource extends JsonResource
|
|
163
|
-
{
|
|
164
|
-
public function toArray($request): array
|
|
165
|
-
{
|
|
166
|
-
return [
|
|
167
|
-
'id' => $this->id,
|
|
168
|
-
'email' => $this->email,
|
|
169
|
-
'name' => $this->name,
|
|
170
|
-
'createdAt' => $this->created_at?->toIso8601String(),
|
|
171
|
-
];
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
### Models
|
|
177
|
-
|
|
178
|
-
- Definir `$fillable` ou `$guarded`
|
|
179
|
-
- `casts` corretos para tipos não-string
|
|
180
|
-
- Relacionamentos explícitos
|
|
181
|
-
|
|
182
|
-
```php
|
|
183
|
-
<?php declare(strict_types=1);
|
|
184
|
-
|
|
185
|
-
namespace App\Models;
|
|
186
|
-
|
|
187
|
-
use Illuminate\Database\Eloquent\Model;
|
|
188
|
-
|
|
189
|
-
final class User extends Model
|
|
190
|
-
{
|
|
191
|
-
protected $fillable = ['email', 'name', 'password'];
|
|
192
|
-
protected $hidden = ['password'];
|
|
193
|
-
protected $casts = [
|
|
194
|
-
'email_verified_at' => 'datetime',
|
|
195
|
-
'created_at' => 'datetime',
|
|
196
|
-
];
|
|
197
|
-
}
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
## Tratamento de exceções
|
|
201
|
-
|
|
202
|
-
Em `bootstrap/app.php` (Laravel 11):
|
|
203
|
-
|
|
204
|
-
```php
|
|
205
|
-
->withExceptions(function (Exceptions $exceptions) {
|
|
206
|
-
$exceptions->render(function (UserAlreadyExistsException $e) {
|
|
207
|
-
return response()->json(['error' => 'User already exists', 'code' => 'USER_EXISTS'], 409);
|
|
208
|
-
});
|
|
209
|
-
$exceptions->render(function (ValidationException $e) {
|
|
210
|
-
return response()->json(['error' => 'Validation failed', 'errors' => $e->errors()], 422);
|
|
211
|
-
});
|
|
212
|
-
})
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
## Transações de banco
|
|
216
|
-
|
|
217
|
-
Sempre que inserir/atualizar múltiplas tabelas:
|
|
218
|
-
|
|
219
|
-
```php
|
|
220
|
-
DB::transaction(function () use ($data) {
|
|
221
|
-
$user = User::create($data);
|
|
222
|
-
UserProfile::create(['user_id' => $user->id, ...]);
|
|
223
|
-
AuditLog::log('user.created', $user);
|
|
224
|
-
});
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
## Testes (Pest)
|
|
228
|
-
|
|
229
|
-
Feature test para cada endpoint:
|
|
230
|
-
|
|
231
|
-
```php
|
|
232
|
-
<?php declare(strict_types=1);
|
|
233
|
-
|
|
234
|
-
use App\Models\User;
|
|
235
|
-
|
|
236
|
-
it('cria usuário com sucesso', function () {
|
|
237
|
-
$payload = ['email' => 'jane@example.com', 'name' => 'Jane', 'password' => 'longsecret123'];
|
|
238
|
-
|
|
239
|
-
$this->actingAs(User::factory()->create(['is_admin' => true]))
|
|
240
|
-
->postJson('/api/users', $payload)
|
|
241
|
-
->assertCreated()
|
|
242
|
-
->assertJsonStructure(['data' => ['id', 'email', 'name', 'createdAt']]);
|
|
243
|
-
|
|
244
|
-
$this->assertDatabaseHas('users', ['email' => 'jane@example.com']);
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
it('rejeita email duplicado', function () {
|
|
248
|
-
User::factory()->create(['email' => 'taken@example.com']);
|
|
249
|
-
$this->actingAs(User::factory()->create(['is_admin' => true]))
|
|
250
|
-
->postJson('/api/users', ['email' => 'taken@example.com', 'name' => 'X', 'password' => 'longsecret123'])
|
|
251
|
-
->assertStatus(409);
|
|
252
|
-
});
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
Cobertura mínima:
|
|
256
|
-
- Resposta de sucesso (200/201)
|
|
257
|
-
- Erro de validação (422)
|
|
258
|
-
- Auth/Autz (401/403)
|
|
259
|
-
- Not Found (404)
|
|
260
|
-
|
|
261
|
-
## Padrões de código
|
|
262
|
-
|
|
263
|
-
- Type hints estritos em todos os métodos (`function x(int $a): User`)
|
|
264
|
-
- Evite `null` — prefira exceção tipada ou `Optional` (collection helper)
|
|
265
|
-
- PHPDoc apenas onde tipo nativo não dá conta (`/** @var User[] $users */`)
|
|
266
|
-
- Comentários explicam o **porquê**, não o **o quê**
|
|
267
|
-
- Use `readonly` em propriedades imutáveis (`public function __construct(public readonly UserRepository $repo) {}`)
|
|
268
|
-
|
|
269
|
-
## Validação estática
|
|
270
|
-
|
|
271
|
-
```bash
|
|
272
|
-
./vendor/bin/phpstan analyse --level=8
|
|
273
|
-
./vendor/bin/pint --test
|
|
274
|
-
./vendor/bin/pest --coverage --min=80
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
## Antipatterns
|
|
278
|
-
|
|
279
|
-
| AP | Antipattern | Sinal | Correção |
|
|
280
|
-
|---|---|---|---|
|
|
281
|
-
| AP-01 | Validação no Controller | `$request->validate([...])` | FormRequest dedicada |
|
|
282
|
-
| AP-02 | Query Eloquent no Controller | `User::where(...)->get()` | Repository |
|
|
283
|
-
| AP-03 | Lógica no Controller | `if ($x) { ... } else { ... }` longo | Service |
|
|
284
|
-
| AP-04 | Retornar Model direto | `return $user` | JsonResource |
|
|
285
|
-
| AP-05 | `$guarded = []` | mass assignment vulnerável | `$fillable` explícito |
|
|
286
|
-
| AP-06 | Sem `declare(strict_types=1)` | Type coercion silenciosa | Adicionar no topo |
|
|
287
|
-
| AP-07 | Múltiplas inserções sem transaction | Estado inconsistente em falha parcial | `DB::transaction()` |
|
|
288
|
-
| AP-08 | Senha hash com `bcrypt()` default cost | Custo baixo | `Hash::make($pwd, ['rounds' => 12])` |
|
|
289
|
-
|
|
290
|
-
## Segurança (combinar com dare-security)
|
|
291
|
-
|
|
292
|
-
- **Senhas:** `Hash::make()` com `rounds >= 12` ou Argon2
|
|
293
|
-
- **Auth:** Sanctum para SPA/mobile, OAuth (Passport) para 3rd-party
|
|
294
|
-
- **Rate limit:** `ThrottleRequests` middleware (`->middleware('throttle:60,1')`)
|
|
295
|
-
- **Headers:** middleware com HSTS, X-Frame-Options, CSP
|
|
296
|
-
- **CORS:** `config/cors.php` específico, nunca `*` em produção
|
|
297
|
-
- **Mass assignment:** `$fillable` SEMPRE, nunca `$guarded = []`
|
|
298
|
-
|
|
299
|
-
## Como aplicar
|
|
300
|
-
|
|
301
|
-
### Passo 1: Audit do projeto
|
|
302
|
-
|
|
303
|
-
```bash
|
|
304
|
-
grep -rn "request()->validate" app/Http/Controllers/ # AP-01
|
|
305
|
-
grep -rn "::where\|::find" app/Http/Controllers/ # AP-02
|
|
306
|
-
./vendor/bin/phpstan analyse --level=8 # tipos
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
### Passo 2: Migrar Controllers para FormRequests
|
|
310
|
-
|
|
311
|
-
Para cada `$request->validate(...)`, gerar FormRequest correspondente:
|
|
312
|
-
|
|
313
|
-
```bash
|
|
314
|
-
php artisan make:request StoreUserRequest
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
### Passo 3: Extrair Services
|
|
318
|
-
|
|
319
|
-
Para cada Controller com lógica > 10 linhas, criar Service correspondente.
|
|
320
|
-
|
|
321
|
-
### Passo 4: Adicionar Repositories
|
|
322
|
-
|
|
323
|
-
Para cada Controller com query Eloquent direta, criar Repository.
|
|
324
|
-
|
|
325
|
-
### Passo 5: Adicionar Resources
|
|
326
|
-
|
|
327
|
-
Substituir `return $user` por `return new UserResource($user)`.
|
|
328
|
-
|
|
329
|
-
## Dicas
|
|
330
|
-
|
|
331
|
-
- **Combine** com `dare-docker` para containerizar (PHP-FPM + Nginx separados)
|
|
332
|
-
- **Use** `dare-security` para auditoria OWASP em FormRequests
|
|
333
|
-
- **Para realtime**, use Laravel Reverb (Pusher-compatible) ou Soketi
|
|
334
|
-
|
|
335
|
-
---
|
|
336
|
-
|
|
337
|
-
Esta skill é parte do DARE Method e está sob licença MIT.
|
|
1
|
+
---
|
|
2
|
+
name: dare-laravel-api
|
|
3
|
+
description: Padrões DARE para APIs REST em Laravel 11 + PHP 8.3 — Strict Types, FormRequests, Services, JsonResources, Eloquent + casts, tratamento global de exceções, testes Feature/Pest, PHPStan/Larastan, Pint.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# DARE Laravel API Skill
|
|
7
|
+
|
|
8
|
+
Você é um desenvolvedor sênior PHP 8.3 / Laravel 11.x especializado em APIs REST. Seu objetivo é gerar código **limpo, legível, performático e fortemente tipado**, seguindo Layered Design e padrões DARE.
|
|
9
|
+
|
|
10
|
+
## Quando usar
|
|
11
|
+
|
|
12
|
+
- Projeto Laravel novo via DARE
|
|
13
|
+
- Adicionar feature em API Laravel existente
|
|
14
|
+
- Auditar projeto Laravel para conformidade DARE
|
|
15
|
+
- Migrar API antiga (Laravel 8/9/10) para padrões 11.x
|
|
16
|
+
|
|
17
|
+
## Stack canônica
|
|
18
|
+
|
|
19
|
+
- **PHP 8.3** — Strict Types em todos os arquivos (`declare(strict_types=1);`)
|
|
20
|
+
- **Laravel 11.x** — modo API (sem views server-side por default)
|
|
21
|
+
- **Banco** — PostgreSQL (preferido) ou MySQL 8
|
|
22
|
+
- **Testes** — Pest (preferido) ou PHPUnit 11
|
|
23
|
+
- **Análise estática** — PHPStan + Larastan (nível 8)
|
|
24
|
+
- **Formatação** — Laravel Pint (`pint`)
|
|
25
|
+
- **Auth** — Laravel Sanctum (tokens) ou Passport (OAuth)
|
|
26
|
+
|
|
27
|
+
## Layered Design em Laravel
|
|
28
|
+
|
|
29
|
+
Mapeamento DARE → Laravel:
|
|
30
|
+
|
|
31
|
+
| Camada DARE | Pasta Laravel |
|
|
32
|
+
|---|---|
|
|
33
|
+
| Handler | `app/Http/Controllers/` |
|
|
34
|
+
| Service | `app/Services/` |
|
|
35
|
+
| Repository | `app/Repositories/` |
|
|
36
|
+
| Model | `app/Models/` |
|
|
37
|
+
| Presenter | `app/Http/Resources/` |
|
|
38
|
+
|
|
39
|
+
### Controllers (Handlers)
|
|
40
|
+
|
|
41
|
+
- Apenas: receber request → chamar Service → retornar Resource
|
|
42
|
+
- NUNCA: lógica de negócio, queries Eloquent, validação inline
|
|
43
|
+
|
|
44
|
+
```php
|
|
45
|
+
<?php declare(strict_types=1);
|
|
46
|
+
|
|
47
|
+
namespace App\Http\Controllers;
|
|
48
|
+
|
|
49
|
+
use App\Http\Requests\StoreUserRequest;
|
|
50
|
+
use App\Http\Resources\UserResource;
|
|
51
|
+
use App\Services\RegisterUser;
|
|
52
|
+
|
|
53
|
+
final class UserApiController extends Controller
|
|
54
|
+
{
|
|
55
|
+
public function __construct(private RegisterUser $service) {}
|
|
56
|
+
|
|
57
|
+
public function store(StoreUserRequest $request): UserResource
|
|
58
|
+
{
|
|
59
|
+
$user = $this->service->execute($request->validated());
|
|
60
|
+
return new UserResource($user);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### FormRequests (Validação)
|
|
66
|
+
|
|
67
|
+
NUNCA validar inline no Controller. Sempre FormRequest:
|
|
68
|
+
|
|
69
|
+
```php
|
|
70
|
+
<?php declare(strict_types=1);
|
|
71
|
+
|
|
72
|
+
namespace App\Http\Requests;
|
|
73
|
+
|
|
74
|
+
use Illuminate\Foundation\Http\FormRequest;
|
|
75
|
+
|
|
76
|
+
final class StoreUserRequest extends FormRequest
|
|
77
|
+
{
|
|
78
|
+
public function authorize(): bool
|
|
79
|
+
{
|
|
80
|
+
return $this->user()->can('create', User::class);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public function rules(): array
|
|
84
|
+
{
|
|
85
|
+
return [
|
|
86
|
+
'email' => ['required', 'email', 'unique:users,email'],
|
|
87
|
+
'password' => ['required', 'string', 'min:12'],
|
|
88
|
+
'name' => ['required', 'string', 'max:255'],
|
|
89
|
+
];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Services (Business Logic)
|
|
95
|
+
|
|
96
|
+
Uma operação por classe. Strict types, exceções de domínio próprias.
|
|
97
|
+
|
|
98
|
+
```php
|
|
99
|
+
<?php declare(strict_types=1);
|
|
100
|
+
|
|
101
|
+
namespace App\Services;
|
|
102
|
+
|
|
103
|
+
use App\Exceptions\UserAlreadyExistsException;
|
|
104
|
+
use App\Models\User;
|
|
105
|
+
use App\Repositories\UserRepository;
|
|
106
|
+
use Illuminate\Support\Facades\Hash;
|
|
107
|
+
|
|
108
|
+
final class RegisterUser
|
|
109
|
+
{
|
|
110
|
+
public function __construct(private UserRepository $users) {}
|
|
111
|
+
|
|
112
|
+
public function execute(array $data): User
|
|
113
|
+
{
|
|
114
|
+
if ($this->users->existsByEmail($data['email'])) {
|
|
115
|
+
throw new UserAlreadyExistsException();
|
|
116
|
+
}
|
|
117
|
+
return $this->users->create([
|
|
118
|
+
'email' => $data['email'],
|
|
119
|
+
'name' => $data['name'],
|
|
120
|
+
'password' => Hash::make($data['password']),
|
|
121
|
+
]);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Repositories (Data Access)
|
|
127
|
+
|
|
128
|
+
Abstrai Eloquent. Service só conhece o Repository, não o Model direto.
|
|
129
|
+
|
|
130
|
+
```php
|
|
131
|
+
<?php declare(strict_types=1);
|
|
132
|
+
|
|
133
|
+
namespace App\Repositories;
|
|
134
|
+
|
|
135
|
+
use App\Models\User;
|
|
136
|
+
|
|
137
|
+
final class UserRepository
|
|
138
|
+
{
|
|
139
|
+
public function existsByEmail(string $email): bool
|
|
140
|
+
{
|
|
141
|
+
return User::where('email', $email)->exists();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
public function create(array $data): User
|
|
145
|
+
{
|
|
146
|
+
return User::create($data);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Resources (Presentation)
|
|
152
|
+
|
|
153
|
+
Nunca retorne Model direto do Controller. Sempre passe por JsonResource.
|
|
154
|
+
|
|
155
|
+
```php
|
|
156
|
+
<?php declare(strict_types=1);
|
|
157
|
+
|
|
158
|
+
namespace App\Http\Resources;
|
|
159
|
+
|
|
160
|
+
use Illuminate\Http\Resources\Json\JsonResource;
|
|
161
|
+
|
|
162
|
+
final class UserResource extends JsonResource
|
|
163
|
+
{
|
|
164
|
+
public function toArray($request): array
|
|
165
|
+
{
|
|
166
|
+
return [
|
|
167
|
+
'id' => $this->id,
|
|
168
|
+
'email' => $this->email,
|
|
169
|
+
'name' => $this->name,
|
|
170
|
+
'createdAt' => $this->created_at?->toIso8601String(),
|
|
171
|
+
];
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Models
|
|
177
|
+
|
|
178
|
+
- Definir `$fillable` ou `$guarded`
|
|
179
|
+
- `casts` corretos para tipos não-string
|
|
180
|
+
- Relacionamentos explícitos
|
|
181
|
+
|
|
182
|
+
```php
|
|
183
|
+
<?php declare(strict_types=1);
|
|
184
|
+
|
|
185
|
+
namespace App\Models;
|
|
186
|
+
|
|
187
|
+
use Illuminate\Database\Eloquent\Model;
|
|
188
|
+
|
|
189
|
+
final class User extends Model
|
|
190
|
+
{
|
|
191
|
+
protected $fillable = ['email', 'name', 'password'];
|
|
192
|
+
protected $hidden = ['password'];
|
|
193
|
+
protected $casts = [
|
|
194
|
+
'email_verified_at' => 'datetime',
|
|
195
|
+
'created_at' => 'datetime',
|
|
196
|
+
];
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Tratamento de exceções
|
|
201
|
+
|
|
202
|
+
Em `bootstrap/app.php` (Laravel 11):
|
|
203
|
+
|
|
204
|
+
```php
|
|
205
|
+
->withExceptions(function (Exceptions $exceptions) {
|
|
206
|
+
$exceptions->render(function (UserAlreadyExistsException $e) {
|
|
207
|
+
return response()->json(['error' => 'User already exists', 'code' => 'USER_EXISTS'], 409);
|
|
208
|
+
});
|
|
209
|
+
$exceptions->render(function (ValidationException $e) {
|
|
210
|
+
return response()->json(['error' => 'Validation failed', 'errors' => $e->errors()], 422);
|
|
211
|
+
});
|
|
212
|
+
})
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Transações de banco
|
|
216
|
+
|
|
217
|
+
Sempre que inserir/atualizar múltiplas tabelas:
|
|
218
|
+
|
|
219
|
+
```php
|
|
220
|
+
DB::transaction(function () use ($data) {
|
|
221
|
+
$user = User::create($data);
|
|
222
|
+
UserProfile::create(['user_id' => $user->id, ...]);
|
|
223
|
+
AuditLog::log('user.created', $user);
|
|
224
|
+
});
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Testes (Pest)
|
|
228
|
+
|
|
229
|
+
Feature test para cada endpoint:
|
|
230
|
+
|
|
231
|
+
```php
|
|
232
|
+
<?php declare(strict_types=1);
|
|
233
|
+
|
|
234
|
+
use App\Models\User;
|
|
235
|
+
|
|
236
|
+
it('cria usuário com sucesso', function () {
|
|
237
|
+
$payload = ['email' => 'jane@example.com', 'name' => 'Jane', 'password' => 'longsecret123'];
|
|
238
|
+
|
|
239
|
+
$this->actingAs(User::factory()->create(['is_admin' => true]))
|
|
240
|
+
->postJson('/api/users', $payload)
|
|
241
|
+
->assertCreated()
|
|
242
|
+
->assertJsonStructure(['data' => ['id', 'email', 'name', 'createdAt']]);
|
|
243
|
+
|
|
244
|
+
$this->assertDatabaseHas('users', ['email' => 'jane@example.com']);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it('rejeita email duplicado', function () {
|
|
248
|
+
User::factory()->create(['email' => 'taken@example.com']);
|
|
249
|
+
$this->actingAs(User::factory()->create(['is_admin' => true]))
|
|
250
|
+
->postJson('/api/users', ['email' => 'taken@example.com', 'name' => 'X', 'password' => 'longsecret123'])
|
|
251
|
+
->assertStatus(409);
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Cobertura mínima:
|
|
256
|
+
- Resposta de sucesso (200/201)
|
|
257
|
+
- Erro de validação (422)
|
|
258
|
+
- Auth/Autz (401/403)
|
|
259
|
+
- Not Found (404)
|
|
260
|
+
|
|
261
|
+
## Padrões de código
|
|
262
|
+
|
|
263
|
+
- Type hints estritos em todos os métodos (`function x(int $a): User`)
|
|
264
|
+
- Evite `null` — prefira exceção tipada ou `Optional` (collection helper)
|
|
265
|
+
- PHPDoc apenas onde tipo nativo não dá conta (`/** @var User[] $users */`)
|
|
266
|
+
- Comentários explicam o **porquê**, não o **o quê**
|
|
267
|
+
- Use `readonly` em propriedades imutáveis (`public function __construct(public readonly UserRepository $repo) {}`)
|
|
268
|
+
|
|
269
|
+
## Validação estática
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
./vendor/bin/phpstan analyse --level=8
|
|
273
|
+
./vendor/bin/pint --test
|
|
274
|
+
./vendor/bin/pest --coverage --min=80
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Antipatterns
|
|
278
|
+
|
|
279
|
+
| AP | Antipattern | Sinal | Correção |
|
|
280
|
+
|---|---|---|---|
|
|
281
|
+
| AP-01 | Validação no Controller | `$request->validate([...])` | FormRequest dedicada |
|
|
282
|
+
| AP-02 | Query Eloquent no Controller | `User::where(...)->get()` | Repository |
|
|
283
|
+
| AP-03 | Lógica no Controller | `if ($x) { ... } else { ... }` longo | Service |
|
|
284
|
+
| AP-04 | Retornar Model direto | `return $user` | JsonResource |
|
|
285
|
+
| AP-05 | `$guarded = []` | mass assignment vulnerável | `$fillable` explícito |
|
|
286
|
+
| AP-06 | Sem `declare(strict_types=1)` | Type coercion silenciosa | Adicionar no topo |
|
|
287
|
+
| AP-07 | Múltiplas inserções sem transaction | Estado inconsistente em falha parcial | `DB::transaction()` |
|
|
288
|
+
| AP-08 | Senha hash com `bcrypt()` default cost | Custo baixo | `Hash::make($pwd, ['rounds' => 12])` |
|
|
289
|
+
|
|
290
|
+
## Segurança (combinar com dare-security)
|
|
291
|
+
|
|
292
|
+
- **Senhas:** `Hash::make()` com `rounds >= 12` ou Argon2
|
|
293
|
+
- **Auth:** Sanctum para SPA/mobile, OAuth (Passport) para 3rd-party
|
|
294
|
+
- **Rate limit:** `ThrottleRequests` middleware (`->middleware('throttle:60,1')`)
|
|
295
|
+
- **Headers:** middleware com HSTS, X-Frame-Options, CSP
|
|
296
|
+
- **CORS:** `config/cors.php` específico, nunca `*` em produção
|
|
297
|
+
- **Mass assignment:** `$fillable` SEMPRE, nunca `$guarded = []`
|
|
298
|
+
|
|
299
|
+
## Como aplicar
|
|
300
|
+
|
|
301
|
+
### Passo 1: Audit do projeto
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
grep -rn "request()->validate" app/Http/Controllers/ # AP-01
|
|
305
|
+
grep -rn "::where\|::find" app/Http/Controllers/ # AP-02
|
|
306
|
+
./vendor/bin/phpstan analyse --level=8 # tipos
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Passo 2: Migrar Controllers para FormRequests
|
|
310
|
+
|
|
311
|
+
Para cada `$request->validate(...)`, gerar FormRequest correspondente:
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
php artisan make:request StoreUserRequest
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Passo 3: Extrair Services
|
|
318
|
+
|
|
319
|
+
Para cada Controller com lógica > 10 linhas, criar Service correspondente.
|
|
320
|
+
|
|
321
|
+
### Passo 4: Adicionar Repositories
|
|
322
|
+
|
|
323
|
+
Para cada Controller com query Eloquent direta, criar Repository.
|
|
324
|
+
|
|
325
|
+
### Passo 5: Adicionar Resources
|
|
326
|
+
|
|
327
|
+
Substituir `return $user` por `return new UserResource($user)`.
|
|
328
|
+
|
|
329
|
+
## Dicas
|
|
330
|
+
|
|
331
|
+
- **Combine** com `dare-docker` para containerizar (PHP-FPM + Nginx separados)
|
|
332
|
+
- **Use** `dare-security` para auditoria OWASP em FormRequests
|
|
333
|
+
- **Para realtime**, use Laravel Reverb (Pusher-compatible) ou Soketi
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
Esta skill é parte do DARE Method e está sob licença MIT.
|