@dewtech/dare-cli 3.0.0 → 3.2.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/README.md +47 -39
- package/dist/__tests__/ensure-skills.test.d.ts +2 -0
- package/dist/__tests__/ensure-skills.test.d.ts.map +1 -0
- package/dist/__tests__/ensure-skills.test.js +67 -0
- package/dist/__tests__/ensure-skills.test.js.map +1 -0
- package/dist/__tests__/ide-command-parity.test.d.ts +2 -0
- package/dist/__tests__/ide-command-parity.test.d.ts.map +1 -0
- package/dist/__tests__/ide-command-parity.test.js +58 -0
- package/dist/__tests__/ide-command-parity.test.js.map +1 -0
- package/dist/__tests__/reverse-collection.test.d.ts +2 -0
- package/dist/__tests__/reverse-collection.test.d.ts.map +1 -0
- package/dist/__tests__/reverse-collection.test.js +87 -0
- package/dist/__tests__/reverse-collection.test.js.map +1 -0
- package/dist/bin/dare.js +1 -3
- package/dist/bin/dare.js.map +1 -1
- package/dist/commands/__tests__/init.integration.spec.d.ts +2 -0
- package/dist/commands/__tests__/init.integration.spec.d.ts.map +1 -0
- package/dist/commands/__tests__/init.integration.spec.js +134 -0
- package/dist/commands/__tests__/init.integration.spec.js.map +1 -0
- package/dist/commands/dna.d.ts.map +1 -1
- package/dist/commands/dna.js +4 -0
- package/dist/commands/dna.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +84 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +4 -0
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/new.d.ts.map +1 -1
- package/dist/commands/new.js +2 -1
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/reverse.d.ts.map +1 -1
- package/dist/commands/reverse.js +27 -8
- package/dist/commands/reverse.js.map +1 -1
- package/dist/mcp-server/bin/server.js +0 -0
- package/dist/stacks/__tests__/dna-emitter.spec.d.ts +2 -0
- package/dist/stacks/__tests__/dna-emitter.spec.d.ts.map +1 -0
- package/dist/stacks/__tests__/dna-emitter.spec.js +207 -0
- package/dist/stacks/__tests__/dna-emitter.spec.js.map +1 -0
- package/dist/stacks/__tests__/dna.spec.d.ts +2 -0
- package/dist/stacks/__tests__/dna.spec.d.ts.map +1 -0
- package/dist/stacks/__tests__/dna.spec.js +211 -0
- package/dist/stacks/__tests__/dna.spec.js.map +1 -0
- package/dist/stacks/__tests__/parity-rails.fixture.json +228 -0
- package/dist/stacks/__tests__/parity-rails.spec.d.ts +2 -0
- package/dist/stacks/__tests__/parity-rails.spec.d.ts.map +1 -0
- package/dist/stacks/__tests__/parity-rails.spec.js +99 -0
- package/dist/stacks/__tests__/parity-rails.spec.js.map +1 -0
- package/dist/stacks/__tests__/registry.spec.d.ts +2 -0
- package/dist/stacks/__tests__/registry.spec.d.ts.map +1 -0
- package/dist/stacks/__tests__/registry.spec.js +101 -0
- package/dist/stacks/__tests__/registry.spec.js.map +1 -0
- package/dist/stacks/__tests__/template-engine.spec.d.ts +2 -0
- package/dist/stacks/__tests__/template-engine.spec.d.ts.map +1 -0
- package/dist/stacks/__tests__/template-engine.spec.js +149 -0
- package/dist/stacks/__tests__/template-engine.spec.js.map +1 -0
- package/dist/stacks/dna-emitter.d.ts +45 -0
- package/dist/stacks/dna-emitter.d.ts.map +1 -0
- package/dist/stacks/dna-emitter.js +267 -0
- package/dist/stacks/dna-emitter.js.map +1 -0
- package/dist/stacks/go-gin/__tests__/scaffold.spec.d.ts +2 -0
- package/dist/stacks/go-gin/__tests__/scaffold.spec.d.ts.map +1 -0
- package/dist/stacks/go-gin/__tests__/scaffold.spec.js +221 -0
- package/dist/stacks/go-gin/__tests__/scaffold.spec.js.map +1 -0
- package/dist/stacks/go-gin/scaffold.d.ts +3 -0
- package/dist/stacks/go-gin/scaffold.d.ts.map +1 -0
- package/dist/stacks/go-gin/scaffold.js +105 -0
- package/dist/stacks/go-gin/scaffold.js.map +1 -0
- package/dist/stacks/go-stdlib/__tests__/scaffold.spec.d.ts +2 -0
- package/dist/stacks/go-stdlib/__tests__/scaffold.spec.d.ts.map +1 -0
- package/dist/stacks/go-stdlib/__tests__/scaffold.spec.js +215 -0
- package/dist/stacks/go-stdlib/__tests__/scaffold.spec.js.map +1 -0
- package/dist/stacks/go-stdlib/scaffold.d.ts +3 -0
- package/dist/stacks/go-stdlib/scaffold.d.ts.map +1 -0
- package/dist/stacks/go-stdlib/scaffold.js +106 -0
- package/dist/stacks/go-stdlib/scaffold.js.map +1 -0
- package/dist/stacks/mcp-go/__tests__/scaffold.spec.d.ts +2 -0
- package/dist/stacks/mcp-go/__tests__/scaffold.spec.d.ts.map +1 -0
- package/dist/stacks/mcp-go/__tests__/scaffold.spec.js +203 -0
- package/dist/stacks/mcp-go/__tests__/scaffold.spec.js.map +1 -0
- package/dist/stacks/mcp-go/scaffold.d.ts +3 -0
- package/dist/stacks/mcp-go/scaffold.d.ts.map +1 -0
- package/dist/stacks/mcp-go/scaffold.js +94 -0
- package/dist/stacks/mcp-go/scaffold.js.map +1 -0
- package/dist/stacks/mcp-node-ts/__tests__/scaffold.spec.d.ts +2 -0
- package/dist/stacks/mcp-node-ts/__tests__/scaffold.spec.d.ts.map +1 -0
- package/dist/stacks/mcp-node-ts/__tests__/scaffold.spec.js +236 -0
- package/dist/stacks/mcp-node-ts/__tests__/scaffold.spec.js.map +1 -0
- package/dist/stacks/mcp-node-ts/scaffold.d.ts +3 -0
- package/dist/stacks/mcp-node-ts/scaffold.d.ts.map +1 -0
- package/dist/stacks/mcp-node-ts/scaffold.js +95 -0
- package/dist/stacks/mcp-node-ts/scaffold.js.map +1 -0
- package/dist/stacks/mcp-python/__tests__/scaffold.spec.d.ts +2 -0
- package/dist/stacks/mcp-python/__tests__/scaffold.spec.d.ts.map +1 -0
- package/dist/stacks/mcp-python/__tests__/scaffold.spec.js +228 -0
- package/dist/stacks/mcp-python/__tests__/scaffold.spec.js.map +1 -0
- package/dist/stacks/mcp-python/scaffold.d.ts +3 -0
- package/dist/stacks/mcp-python/scaffold.d.ts.map +1 -0
- package/dist/stacks/mcp-python/scaffold.js +98 -0
- package/dist/stacks/mcp-python/scaffold.js.map +1 -0
- package/dist/stacks/mcp-rust/__tests__/scaffold.spec.d.ts +2 -0
- package/dist/stacks/mcp-rust/__tests__/scaffold.spec.d.ts.map +1 -0
- package/dist/stacks/mcp-rust/__tests__/scaffold.spec.js +213 -0
- package/dist/stacks/mcp-rust/__tests__/scaffold.spec.js.map +1 -0
- package/dist/stacks/mcp-rust/scaffold.d.ts +3 -0
- package/dist/stacks/mcp-rust/scaffold.d.ts.map +1 -0
- package/dist/stacks/mcp-rust/scaffold.js +98 -0
- package/dist/stacks/mcp-rust/scaffold.js.map +1 -0
- package/dist/stacks/node-nestjs/__tests__/scaffold.spec.d.ts +2 -0
- package/dist/stacks/node-nestjs/__tests__/scaffold.spec.d.ts.map +1 -0
- package/dist/stacks/node-nestjs/__tests__/scaffold.spec.js +172 -0
- package/dist/stacks/node-nestjs/__tests__/scaffold.spec.js.map +1 -0
- package/dist/stacks/node-nestjs/scaffold.d.ts +3 -0
- package/dist/stacks/node-nestjs/scaffold.d.ts.map +1 -0
- package/dist/stacks/node-nestjs/scaffold.js +117 -0
- package/dist/stacks/node-nestjs/scaffold.js.map +1 -0
- package/dist/stacks/php-laravel/__tests__/scaffold.spec.d.ts +2 -0
- package/dist/stacks/php-laravel/__tests__/scaffold.spec.d.ts.map +1 -0
- package/dist/stacks/php-laravel/__tests__/scaffold.spec.js +205 -0
- package/dist/stacks/php-laravel/__tests__/scaffold.spec.js.map +1 -0
- package/dist/stacks/php-laravel/scaffold.d.ts +3 -0
- package/dist/stacks/php-laravel/scaffold.d.ts.map +1 -0
- package/dist/stacks/php-laravel/scaffold.js +109 -0
- package/dist/stacks/php-laravel/scaffold.js.map +1 -0
- package/dist/stacks/python-fastapi/__tests__/scaffold.spec.d.ts +2 -0
- package/dist/stacks/python-fastapi/__tests__/scaffold.spec.d.ts.map +1 -0
- package/dist/stacks/python-fastapi/__tests__/scaffold.spec.js +168 -0
- package/dist/stacks/python-fastapi/__tests__/scaffold.spec.js.map +1 -0
- package/dist/stacks/python-fastapi/scaffold.d.ts +3 -0
- package/dist/stacks/python-fastapi/scaffold.d.ts.map +1 -0
- package/dist/stacks/python-fastapi/scaffold.js +108 -0
- package/dist/stacks/python-fastapi/scaffold.js.map +1 -0
- package/dist/stacks/registry.d.ts +38 -0
- package/dist/stacks/registry.d.ts.map +1 -0
- package/dist/stacks/registry.js +153 -0
- package/dist/stacks/registry.js.map +1 -0
- package/dist/stacks/ruby-rails-8/__tests__/scaffold.spec.d.ts +6 -0
- package/dist/stacks/ruby-rails-8/__tests__/scaffold.spec.d.ts.map +1 -0
- package/dist/stacks/ruby-rails-8/__tests__/scaffold.spec.js +604 -0
- package/dist/stacks/ruby-rails-8/__tests__/scaffold.spec.js.map +1 -0
- package/dist/stacks/ruby-rails-8/scaffold.d.ts +91 -0
- package/dist/stacks/ruby-rails-8/scaffold.d.ts.map +1 -0
- package/dist/stacks/ruby-rails-8/scaffold.js +410 -0
- package/dist/stacks/ruby-rails-8/scaffold.js.map +1 -0
- package/dist/stacks/rust-axum/__tests__/scaffold.spec.d.ts +2 -0
- package/dist/stacks/rust-axum/__tests__/scaffold.spec.d.ts.map +1 -0
- package/dist/stacks/rust-axum/__tests__/scaffold.spec.js +203 -0
- package/dist/stacks/rust-axum/__tests__/scaffold.spec.js.map +1 -0
- package/dist/stacks/rust-axum/scaffold.d.ts +3 -0
- package/dist/stacks/rust-axum/scaffold.d.ts.map +1 -0
- package/dist/stacks/rust-axum/scaffold.js +105 -0
- package/dist/stacks/rust-axum/scaffold.js.map +1 -0
- package/dist/stacks/template-engine.d.ts +38 -0
- package/dist/stacks/template-engine.d.ts.map +1 -0
- package/dist/stacks/template-engine.js +134 -0
- package/dist/stacks/template-engine.js.map +1 -0
- package/dist/stacks/types.d.ts +69 -0
- package/dist/stacks/types.d.ts.map +1 -0
- package/dist/stacks/types.js +29 -0
- package/dist/stacks/types.js.map +1 -0
- package/dist/utils/datamodel.d.ts.map +1 -1
- package/dist/utils/datamodel.js +97 -20
- package/dist/utils/datamodel.js.map +1 -1
- package/dist/utils/project-generator.d.ts +22 -1
- package/dist/utils/project-generator.d.ts.map +1 -1
- package/dist/utils/project-generator.js +85 -7
- package/dist/utils/project-generator.js.map +1 -1
- package/dist/utils/reverse-facts.d.ts +3 -2
- package/dist/utils/reverse-facts.d.ts.map +1 -1
- package/dist/utils/reverse-facts.js +89 -8
- package/dist/utils/reverse-facts.js.map +1 -1
- package/dist/utils/stack-bootstrap.d.ts +3 -2
- package/dist/utils/stack-bootstrap.d.ts.map +1 -1
- package/dist/utils/stack-bootstrap.js +46 -16
- package/dist/utils/stack-bootstrap.js.map +1 -1
- package/package.json +91 -87
- package/templates/ide/antigravity/.agents/skills/dare-bootstrap/SKILL.md +32 -0
- package/templates/ide/antigravity/.agents/skills/dare-dag/SKILL.md +32 -0
- package/templates/ide/antigravity/.agents/skills/dare-discover/SKILL.md +33 -0
- package/templates/ide/antigravity/.agents/skills/dare-graph/SKILL.md +35 -0
- package/templates/ide/antigravity/.agents/skills/dare-info/SKILL.md +31 -0
- package/templates/ide/antigravity/.agents/skills/dare-init/SKILL.md +35 -0
- package/templates/ide/antigravity/.agents/skills/dare-skill/SKILL.md +35 -0
- package/templates/ide/antigravity/.agents/skills/dare-update/SKILL.md +33 -0
- package/templates/ide/antigravity/.agents/skills/dare-validate/SKILL.md +33 -0
- package/templates/ide/antigravity/.agents/skills/dare-welcome/SKILL.md +30 -0
- package/templates/ide/claude/.claude/commands/dare-bootstrap.md +27 -0
- package/templates/ide/claude/.claude/commands/dare-dag.md +27 -0
- package/templates/ide/claude/.claude/commands/dare-discover.md +28 -0
- package/templates/ide/claude/.claude/commands/dare-graph.md +30 -0
- package/templates/ide/claude/.claude/commands/dare-info.md +26 -0
- package/templates/ide/claude/.claude/commands/dare-init.md +30 -0
- package/templates/ide/claude/.claude/commands/dare-skill.md +30 -0
- package/templates/ide/claude/.claude/commands/dare-update.md +28 -0
- package/templates/ide/claude/.claude/commands/dare-validate.md +28 -0
- package/templates/ide/claude/.claude/commands/dare-welcome.md +25 -0
- package/templates/ide/cursor/.cursor/commands/{generate-blueprint.md → dare-blueprint.md} +1 -1
- package/templates/ide/cursor/.cursor/commands/dare-bootstrap.md +27 -0
- package/templates/ide/cursor/.cursor/commands/{run-dag.md → dare-dag-run.md} +1 -1
- package/templates/ide/cursor/.cursor/commands/{dag-viz.md → dare-dag-viz.md} +1 -1
- package/templates/ide/cursor/.cursor/commands/dare-dag.md +27 -0
- package/templates/ide/cursor/.cursor/commands/{generate-design.md → dare-design.md} +1 -1
- package/templates/ide/cursor/.cursor/commands/dare-discover.md +28 -0
- package/templates/ide/cursor/.cursor/commands/dare-dna.md +75 -0
- package/templates/ide/cursor/.cursor/commands/{generate-docker-compose.md → dare-docker-compose.md} +1 -1
- package/templates/ide/cursor/.cursor/commands/{generate-dockerfile.md → dare-dockerfile.md} +1 -1
- package/templates/ide/cursor/.cursor/commands/{execute-task.md → dare-execute.md} +1 -1
- package/templates/ide/cursor/.cursor/commands/dare-graph.md +30 -0
- package/templates/ide/cursor/.cursor/commands/dare-info.md +26 -0
- package/templates/ide/cursor/.cursor/commands/dare-init.md +30 -0
- package/templates/ide/cursor/.cursor/commands/dare-migrate.md +72 -0
- package/templates/ide/cursor/.cursor/commands/{refine-task.md → dare-refine.md} +1 -1
- package/templates/ide/cursor/.cursor/commands/dare-reverse.md +139 -0
- package/templates/ide/cursor/.cursor/commands/{review-task.md → dare-review.md} +1 -1
- package/templates/ide/cursor/.cursor/commands/dare-skill.md +30 -0
- package/templates/ide/cursor/.cursor/commands/{generate-tasks.md → dare-tasks.md} +1 -1
- package/templates/ide/cursor/.cursor/commands/{telemetry-report.md → dare-telemetry.md} +1 -1
- package/templates/ide/cursor/.cursor/commands/dare-update.md +28 -0
- package/templates/ide/cursor/.cursor/commands/dare-validate.md +28 -0
- package/templates/ide/cursor/.cursor/commands/dare-welcome.md +25 -0
- package/templates/stacks/go-gin/.dare/skills.yml +11 -0
- package/templates/stacks/go-gin/.env.example +24 -0
- package/templates/stacks/go-gin/.github/workflows/dare-ci.yml +42 -0
- package/templates/stacks/go-gin/README.md.tpl +38 -0
- package/templates/stacks/go-gin/cmd/server/main.go.tpl +78 -0
- package/templates/stacks/go-gin/db/migrations/0001_create_users.down.sql +2 -0
- package/templates/stacks/go-gin/db/migrations/0001_create_users.up.sql +12 -0
- package/templates/stacks/go-gin/db/queries/users.sql +23 -0
- package/templates/stacks/go-gin/gitignore +7 -0
- package/templates/stacks/go-gin/go.mod.tpl +17 -0
- package/templates/stacks/go-gin/internal/config/config.go +41 -0
- package/templates/stacks/go-gin/internal/db/postgres.go.tpl +25 -0
- package/templates/stacks/go-gin/internal/handler/auth_handler.go.tpl +72 -0
- package/templates/stacks/go-gin/internal/handler/users_handler.go.tpl +72 -0
- package/templates/stacks/go-gin/internal/handler/ws_handler.go +37 -0
- package/templates/stacks/go-gin/internal/llm/dummy.go +14 -0
- package/templates/stacks/go-gin/internal/llm/provider.go +8 -0
- package/templates/stacks/go-gin/internal/middleware/jwt.go.tpl +58 -0
- package/templates/stacks/go-gin/internal/middleware/rate_limit.go +55 -0
- package/templates/stacks/go-gin/internal/model/user.go +17 -0
- package/templates/stacks/go-gin/internal/repository/users_repository.go.tpl +79 -0
- package/templates/stacks/go-gin/internal/service/auth_service.go.tpl +55 -0
- package/templates/stacks/go-gin/internal/service/users_service.go.tpl +53 -0
- package/templates/stacks/go-gin/llms.txt.tpl +54 -0
- package/templates/stacks/go-gin/openapi.json.tpl +46 -0
- package/templates/stacks/go-gin/sqlc.yaml +14 -0
- package/templates/stacks/go-gin/tests/smoke_test.go.tpl +22 -0
- package/templates/stacks/go-stdlib/.dare/skills.yml +11 -0
- package/templates/stacks/go-stdlib/.env.example +24 -0
- package/templates/stacks/go-stdlib/.github/workflows/dare-ci.yml +42 -0
- package/templates/stacks/go-stdlib/README.md.tpl +41 -0
- package/templates/stacks/go-stdlib/cmd/server/main.go.tpl +82 -0
- package/templates/stacks/go-stdlib/db/migrations/0001_create_users.down.sql +2 -0
- package/templates/stacks/go-stdlib/db/migrations/0001_create_users.up.sql +12 -0
- package/templates/stacks/go-stdlib/db/queries/users.sql +23 -0
- package/templates/stacks/go-stdlib/gitignore +6 -0
- package/templates/stacks/go-stdlib/go.mod.tpl +15 -0
- package/templates/stacks/go-stdlib/internal/config/config.go +41 -0
- package/templates/stacks/go-stdlib/internal/db/postgres.go.tpl +24 -0
- package/templates/stacks/go-stdlib/internal/handler/auth_handler.go.tpl +71 -0
- package/templates/stacks/go-stdlib/internal/handler/users_handler.go.tpl +84 -0
- package/templates/stacks/go-stdlib/internal/handler/ws_handler.go +36 -0
- package/templates/stacks/go-stdlib/internal/httpx/json.go +32 -0
- package/templates/stacks/go-stdlib/internal/llm/dummy.go +14 -0
- package/templates/stacks/go-stdlib/internal/llm/provider.go +8 -0
- package/templates/stacks/go-stdlib/internal/middleware/chain.go +21 -0
- package/templates/stacks/go-stdlib/internal/middleware/cors.go +27 -0
- package/templates/stacks/go-stdlib/internal/middleware/jwt.go.tpl +51 -0
- package/templates/stacks/go-stdlib/internal/middleware/rate_limit.go +81 -0
- package/templates/stacks/go-stdlib/internal/model/user.go +17 -0
- package/templates/stacks/go-stdlib/internal/repository/users_repository.go.tpl +75 -0
- package/templates/stacks/go-stdlib/internal/service/auth_service.go.tpl +55 -0
- package/templates/stacks/go-stdlib/internal/service/users_service.go.tpl +53 -0
- package/templates/stacks/go-stdlib/llms.txt.tpl +60 -0
- package/templates/stacks/go-stdlib/openapi.json.tpl +46 -0
- package/templates/stacks/go-stdlib/sqlc.yaml +14 -0
- package/templates/stacks/go-stdlib/tests/smoke_test.go.tpl +45 -0
- package/templates/stacks/mcp-go/.dare/skills.yml +8 -0
- package/templates/stacks/mcp-go/.env.example +14 -0
- package/templates/stacks/mcp-go/.github/workflows/dare-ci.yml +42 -0
- package/templates/stacks/mcp-go/README.md.tpl +50 -0
- package/templates/stacks/mcp-go/cmd/server/main.go.tpl +62 -0
- package/templates/stacks/mcp-go/gitignore +6 -0
- package/templates/stacks/mcp-go/go.mod.tpl +9 -0
- package/templates/stacks/mcp-go/internal/prompts/summarize.go +9 -0
- package/templates/stacks/mcp-go/internal/server/server.go.tpl +80 -0
- package/templates/stacks/mcp-go/internal/tools/echo.go +15 -0
- package/templates/stacks/mcp-go/internal/transports/http.go.tpl +21 -0
- package/templates/stacks/mcp-go/internal/transports/sse.go.tpl +17 -0
- package/templates/stacks/mcp-go/internal/transports/stdio.go.tpl +14 -0
- package/templates/stacks/mcp-go/llms.txt.tpl +60 -0
- package/templates/stacks/mcp-go/openapi.json.tpl +31 -0
- package/templates/stacks/mcp-go/tests/echo_test.go.tpl +37 -0
- package/templates/stacks/mcp-node-ts/.dare/skills.yml +8 -0
- package/templates/stacks/mcp-node-ts/.env.example +16 -0
- package/templates/stacks/mcp-node-ts/.github/workflows/dare-ci.yml +54 -0
- package/templates/stacks/mcp-node-ts/README.md.hbs +49 -0
- package/templates/stacks/mcp-node-ts/gitignore +7 -0
- package/templates/stacks/mcp-node-ts/llms.txt.hbs +61 -0
- package/templates/stacks/mcp-node-ts/openapi.json.hbs +39 -0
- package/templates/stacks/mcp-node-ts/package.json.hbs +35 -0
- package/templates/stacks/mcp-node-ts/src/cli.ts.hbs +71 -0
- package/templates/stacks/mcp-node-ts/src/prompts/index.ts +36 -0
- package/templates/stacks/mcp-node-ts/src/server.ts.hbs +45 -0
- package/templates/stacks/mcp-node-ts/src/tools/echo.ts +23 -0
- package/templates/stacks/mcp-node-ts/src/tools/index.ts +18 -0
- package/templates/stacks/mcp-node-ts/src/transports/http.ts +68 -0
- package/templates/stacks/mcp-node-ts/src/transports/sse.ts +58 -0
- package/templates/stacks/mcp-node-ts/src/transports/stdio.ts +5 -0
- package/templates/stacks/mcp-node-ts/tests/echo.test.ts +50 -0
- package/templates/stacks/mcp-node-ts/tsconfig.json +17 -0
- package/templates/stacks/mcp-python/.dare/skills.yml +8 -0
- package/templates/stacks/mcp-python/.env.example +14 -0
- package/templates/stacks/mcp-python/.github/workflows/dare-ci.yml +42 -0
- package/templates/stacks/mcp-python/README.md.j2 +49 -0
- package/templates/stacks/mcp-python/gitignore +12 -0
- package/templates/stacks/mcp-python/llms.txt.j2 +56 -0
- package/templates/stacks/mcp-python/openapi.json.j2 +33 -0
- package/templates/stacks/mcp-python/pyproject.toml.j2 +37 -0
- package/templates/stacks/mcp-python/src/__init__.py +0 -0
- package/templates/stacks/mcp-python/src/cli.py.j2 +68 -0
- package/templates/stacks/mcp-python/src/prompts/__init__.py +0 -0
- package/templates/stacks/mcp-python/src/prompts/summarize.py +10 -0
- package/templates/stacks/mcp-python/src/server.py.j2 +28 -0
- package/templates/stacks/mcp-python/src/tools/__init__.py +0 -0
- package/templates/stacks/mcp-python/src/tools/echo.py +12 -0
- package/templates/stacks/mcp-python/src/transports/__init__.py +0 -0
- package/templates/stacks/mcp-python/src/transports/http.py +12 -0
- package/templates/stacks/mcp-python/src/transports/sse.py +13 -0
- package/templates/stacks/mcp-python/src/transports/stdio.py +6 -0
- package/templates/stacks/mcp-python/tests/__init__.py +0 -0
- package/templates/stacks/mcp-python/tests/test_echo.py +28 -0
- package/templates/stacks/mcp-rust/.dare/skills.yml +8 -0
- package/templates/stacks/mcp-rust/.env.example +14 -0
- package/templates/stacks/mcp-rust/.github/workflows/dare-ci.yml +38 -0
- package/templates/stacks/mcp-rust/Cargo.toml.tera +35 -0
- package/templates/stacks/mcp-rust/README.md.tera +50 -0
- package/templates/stacks/mcp-rust/gitignore +5 -0
- package/templates/stacks/mcp-rust/llms.txt.tera +60 -0
- package/templates/stacks/mcp-rust/openapi.json.tera +31 -0
- package/templates/stacks/mcp-rust/src/cli.rs.tera +33 -0
- package/templates/stacks/mcp-rust/src/lib.rs +6 -0
- package/templates/stacks/mcp-rust/src/main.rs.tera +30 -0
- package/templates/stacks/mcp-rust/src/prompts/mod.rs +1 -0
- package/templates/stacks/mcp-rust/src/prompts/summarize.rs +5 -0
- package/templates/stacks/mcp-rust/src/server.rs.tera +38 -0
- package/templates/stacks/mcp-rust/src/tools/echo.rs +18 -0
- package/templates/stacks/mcp-rust/src/tools/mod.rs +22 -0
- package/templates/stacks/mcp-rust/src/transports/http.rs +27 -0
- package/templates/stacks/mcp-rust/src/transports/mod.rs +3 -0
- package/templates/stacks/mcp-rust/src/transports/sse.rs +33 -0
- package/templates/stacks/mcp-rust/src/transports/stdio.rs +14 -0
- package/templates/stacks/mcp-rust/tests/echo_test.rs.tera +27 -0
- package/templates/stacks/node-nestjs/.dare/skills.yml +11 -0
- package/templates/stacks/node-nestjs/.env.example +21 -0
- package/templates/stacks/node-nestjs/.github/workflows/dare-ci.yml +54 -0
- package/templates/stacks/node-nestjs/README.md.hbs +35 -0
- package/templates/stacks/node-nestjs/gitignore +7 -0
- package/templates/stacks/node-nestjs/llms.txt.hbs +47 -0
- package/templates/stacks/node-nestjs/nest-cli.json +16 -0
- package/templates/stacks/node-nestjs/openapi.json.hbs +75 -0
- package/templates/stacks/node-nestjs/package.json.hbs +57 -0
- package/templates/stacks/node-nestjs/prisma/schema.prisma +25 -0
- package/templates/stacks/node-nestjs/prisma/seed.ts.hbs +25 -0
- package/templates/stacks/node-nestjs/src/app.module.ts +39 -0
- package/templates/stacks/node-nestjs/src/auth/auth.controller.ts +29 -0
- package/templates/stacks/node-nestjs/src/auth/auth.module.ts +25 -0
- package/templates/stacks/node-nestjs/src/auth/auth.service.ts +36 -0
- package/templates/stacks/node-nestjs/src/auth/dto/login-response.dto.ts +9 -0
- package/templates/stacks/node-nestjs/src/auth/dto/login.dto.ts +17 -0
- package/templates/stacks/node-nestjs/src/auth/jwt.strategy.ts +25 -0
- package/templates/stacks/node-nestjs/src/common/filters/problem-details.filter.ts +38 -0
- package/templates/stacks/node-nestjs/src/common/interceptors/json-response.interceptor.ts +13 -0
- package/templates/stacks/node-nestjs/src/main.ts.hbs +44 -0
- package/templates/stacks/node-nestjs/src/prisma/prisma.module.ts +9 -0
- package/templates/stacks/node-nestjs/src/prisma/prisma.service.ts +9 -0
- package/templates/stacks/node-nestjs/src/users/dto/create-user.dto.ts +22 -0
- package/templates/stacks/node-nestjs/src/users/dto/user.dto.ts +15 -0
- package/templates/stacks/node-nestjs/src/users/users.controller.ts +41 -0
- package/templates/stacks/node-nestjs/src/users/users.module.ts +11 -0
- package/templates/stacks/node-nestjs/src/users/users.repository.ts +38 -0
- package/templates/stacks/node-nestjs/src/users/users.service.ts +38 -0
- package/templates/stacks/node-nestjs/tsconfig.build.json +4 -0
- package/templates/stacks/node-nestjs/tsconfig.json +28 -0
- package/templates/stacks/php-laravel/.dare/skills.yml +11 -0
- package/templates/stacks/php-laravel/.env.example +41 -0
- package/templates/stacks/php-laravel/.github/workflows/dare-ci.yml +43 -0
- package/templates/stacks/php-laravel/README.md.hbs +36 -0
- package/templates/stacks/php-laravel/app/Http/Controllers/Api/AuthController.php +36 -0
- package/templates/stacks/php-laravel/app/Http/Controllers/Api/UsersController.php +33 -0
- package/templates/stacks/php-laravel/app/Http/Requests/CreateUserRequest.php +26 -0
- package/templates/stacks/php-laravel/app/Http/Requests/LoginRequest.php +34 -0
- package/templates/stacks/php-laravel/app/Llm/Contracts/LlmProvider.php +12 -0
- package/templates/stacks/php-laravel/app/Llm/Providers/DummyProvider.php +13 -0
- package/templates/stacks/php-laravel/app/Llm/Providers/OpenAiProvider.php +33 -0
- package/templates/stacks/php-laravel/app/Models/User.php +44 -0
- package/templates/stacks/php-laravel/app/Repositories/UsersRepository.php +32 -0
- package/templates/stacks/php-laravel/app/Services/AuthService.php +37 -0
- package/templates/stacks/php-laravel/app/Services/UsersService.php +57 -0
- package/templates/stacks/php-laravel/artisan +12 -0
- package/templates/stacks/php-laravel/bootstrap/app.php +29 -0
- package/templates/stacks/php-laravel/bootstrap/providers.php +5 -0
- package/templates/stacks/php-laravel/composer.json.hbs +58 -0
- package/templates/stacks/php-laravel/config/l5-swagger.php +41 -0
- package/templates/stacks/php-laravel/config/reverb.php +34 -0
- package/templates/stacks/php-laravel/config/sanctum.php +15 -0
- package/templates/stacks/php-laravel/database/migrations/2026_06_01_000001_create_users_table.php +27 -0
- package/templates/stacks/php-laravel/database/seeders/DatabaseSeeder.php +21 -0
- package/templates/stacks/php-laravel/gitignore +23 -0
- package/templates/stacks/php-laravel/llms.txt.hbs +53 -0
- package/templates/stacks/php-laravel/openapi.json.hbs +43 -0
- package/templates/stacks/php-laravel/phpstan.neon +9 -0
- package/templates/stacks/php-laravel/routes/api.php +13 -0
- package/templates/stacks/php-laravel/routes/channels.php +7 -0
- package/templates/stacks/php-laravel/tests/Feature/AuthTest.php +35 -0
- package/templates/stacks/php-laravel/tests/Feature/UsersTest.php +30 -0
- package/templates/stacks/php-laravel/tests/Pest.php +5 -0
- package/templates/stacks/python-fastapi/.dare/skills.yml +11 -0
- package/templates/stacks/python-fastapi/.env.example +21 -0
- package/templates/stacks/python-fastapi/.github/workflows/dare-ci.yml +43 -0
- package/templates/stacks/python-fastapi/README.md.j2 +35 -0
- package/templates/stacks/python-fastapi/alembic/env.py +46 -0
- package/templates/stacks/python-fastapi/alembic/script.py.mako +26 -0
- package/templates/stacks/python-fastapi/alembic/versions/0001_create_users.py.j2 +37 -0
- package/templates/stacks/python-fastapi/alembic.ini.j2 +39 -0
- package/templates/stacks/python-fastapi/app/__init__.py +0 -0
- package/templates/stacks/python-fastapi/app/core/__init__.py +0 -0
- package/templates/stacks/python-fastapi/app/core/config.py +24 -0
- package/templates/stacks/python-fastapi/app/core/security.py +34 -0
- package/templates/stacks/python-fastapi/app/db/__init__.py +0 -0
- package/templates/stacks/python-fastapi/app/db/session.py +22 -0
- package/templates/stacks/python-fastapi/app/main.py.j2 +36 -0
- package/templates/stacks/python-fastapi/app/models/__init__.py +3 -0
- package/templates/stacks/python-fastapi/app/models/user.py +30 -0
- package/templates/stacks/python-fastapi/app/repositories/__init__.py +0 -0
- package/templates/stacks/python-fastapi/app/repositories/user_repository.py +34 -0
- package/templates/stacks/python-fastapi/app/routers/__init__.py +0 -0
- package/templates/stacks/python-fastapi/app/routers/auth.py +37 -0
- package/templates/stacks/python-fastapi/app/routers/users.py +46 -0
- package/templates/stacks/python-fastapi/app/schemas/__init__.py +0 -0
- package/templates/stacks/python-fastapi/app/schemas/user.py +56 -0
- package/templates/stacks/python-fastapi/app/services/__init__.py +0 -0
- package/templates/stacks/python-fastapi/app/services/auth_service.py +22 -0
- package/templates/stacks/python-fastapi/app/services/user_service.py +31 -0
- package/templates/stacks/python-fastapi/gitignore +12 -0
- package/templates/stacks/python-fastapi/llms.txt.j2 +53 -0
- package/templates/stacks/python-fastapi/openapi.json.j2 +43 -0
- package/templates/stacks/python-fastapi/pyproject.toml.j2 +45 -0
- package/templates/stacks/python-fastapi/tests/__init__.py +0 -0
- package/templates/stacks/python-fastapi/tests/test_auth.py +22 -0
- package/templates/stacks/ruby-rails-8/.dare/skills.yml +50 -0
- package/templates/stacks/ruby-rails-8/.env.example +20 -0
- package/templates/stacks/ruby-rails-8/.github/workflows/dare-ci.yml +112 -0
- package/templates/stacks/ruby-rails-8/Gemfile.erb +61 -0
- package/templates/stacks/ruby-rails-8/app/channels/application_cable/channel.rb +11 -0
- package/templates/stacks/ruby-rails-8/app/channels/application_cable/connection.rb +34 -0
- package/templates/stacks/ruby-rails-8/app/channels/dare_updates_channel.rb +18 -0
- package/templates/stacks/ruby-rails-8/app/channels/user_updates_channel.rb +23 -0
- package/templates/stacks/ruby-rails-8/app/controllers/application_controller.rb +44 -0
- package/templates/stacks/ruby-rails-8/app/controllers/concerns/problem_details.rb +93 -0
- package/templates/stacks/ruby-rails-8/app/handlers/summarize_handler.rb +33 -0
- package/templates/stacks/ruby-rails-8/app/handlers/users_handler.rb +68 -0
- package/templates/stacks/ruby-rails-8/app/llm/cache/llm_cache.rb +44 -0
- package/templates/stacks/ruby-rails-8/app/llm/prompts/prompt_loader.rb +54 -0
- package/templates/stacks/ruby-rails-8/app/llm/prompts/summarize_v1.jinja2 +12 -0
- package/templates/stacks/ruby-rails-8/app/llm/providers/dummy_provider.rb +35 -0
- package/templates/stacks/ruby-rails-8/app/llm/providers/llm_provider.rb +67 -0
- package/templates/stacks/ruby-rails-8/app/llm/providers/openai_provider.rb +62 -0
- package/templates/stacks/ruby-rails-8/app/llm/rate_limit/token_bucket.rb +82 -0
- package/templates/stacks/ruby-rails-8/app/llm/validators/summarize_output_schema.json +21 -0
- package/templates/stacks/ruby-rails-8/app/llm/validators/validator.rb +52 -0
- package/templates/stacks/ruby-rails-8/app/models/user.rb +36 -0
- package/templates/stacks/ruby-rails-8/app/presenters/user_presenter.rb +48 -0
- package/templates/stacks/ruby-rails-8/app/repositories/document_repository.rb +57 -0
- package/templates/stacks/ruby-rails-8/app/repositories/user_repository.rb +73 -0
- package/templates/stacks/ruby-rails-8/app/services/create_user_service.rb +67 -0
- package/templates/stacks/ruby-rails-8/app/services/realtime_service.rb +53 -0
- package/templates/stacks/ruby-rails-8/app/services/summarize_document_service.rb +57 -0
- package/templates/stacks/ruby-rails-8/config/dare.yml +42 -0
- package/templates/stacks/ruby-rails-8/config/initializers/dare.rb +31 -0
- package/templates/stacks/ruby-rails-8/config/initializers/rack_attack.rb +64 -0
- package/templates/stacks/ruby-rails-8/config/initializers/rswag_api.rb +12 -0
- package/templates/stacks/ruby-rails-8/lib/tasks/dare.rake +159 -0
- package/templates/stacks/ruby-rails-8/llms.txt.erb +69 -0
- package/templates/stacks/ruby-rails-8/spec/api/summarize_spec.rb +56 -0
- package/templates/stacks/ruby-rails-8/spec/api/users_spec.rb +72 -0
- package/templates/stacks/ruby-rails-8/spec/channels/dare_updates_channel_spec.rb +61 -0
- package/templates/stacks/ruby-rails-8/spec/channels/user_updates_channel_spec.rb +56 -0
- package/templates/stacks/ruby-rails-8/spec/factories/users.rb +27 -0
- package/templates/stacks/ruby-rails-8/spec/handlers/users_handler_spec.rb +88 -0
- package/templates/stacks/ruby-rails-8/spec/rails_helper.rb +31 -0
- package/templates/stacks/ruby-rails-8/spec/services/create_user_service_spec.rb +88 -0
- package/templates/stacks/ruby-rails-8/spec/services/summarize_document_service_spec.rb +142 -0
- package/templates/stacks/ruby-rails-8/spec/swagger_helper.rb +73 -0
- package/templates/stacks/rust-axum/.dare/skills.yml +11 -0
- package/templates/stacks/rust-axum/.env.example +26 -0
- package/templates/stacks/rust-axum/.github/workflows/dare-ci.yml +40 -0
- package/templates/stacks/rust-axum/Cargo.toml.tera +53 -0
- package/templates/stacks/rust-axum/README.md.tera +37 -0
- package/templates/stacks/rust-axum/gitignore +5 -0
- package/templates/stacks/rust-axum/llms.txt.tera +54 -0
- package/templates/stacks/rust-axum/migrations/0001_create_users.sql +13 -0
- package/templates/stacks/rust-axum/openapi.json.tera +46 -0
- package/templates/stacks/rust-axum/src/config.rs +45 -0
- package/templates/stacks/rust-axum/src/errors.rs +48 -0
- package/templates/stacks/rust-axum/src/handlers/auth.rs +48 -0
- package/templates/stacks/rust-axum/src/handlers/mod.rs +3 -0
- package/templates/stacks/rust-axum/src/handlers/users.rs +81 -0
- package/templates/stacks/rust-axum/src/handlers/ws.rs +24 -0
- package/templates/stacks/rust-axum/src/lib.rs +19 -0
- package/templates/stacks/rust-axum/src/llm/mod.rs +1 -0
- package/templates/stacks/rust-axum/src/llm/provider.rs +48 -0
- package/templates/stacks/rust-axum/src/main.rs.tera +64 -0
- package/templates/stacks/rust-axum/src/middleware/auth.rs +20 -0
- package/templates/stacks/rust-axum/src/middleware/mod.rs +2 -0
- package/templates/stacks/rust-axum/src/middleware/rate_limit.rs +27 -0
- package/templates/stacks/rust-axum/src/models/mod.rs +1 -0
- package/templates/stacks/rust-axum/src/models/user.rs +13 -0
- package/templates/stacks/rust-axum/src/repositories/mod.rs +1 -0
- package/templates/stacks/rust-axum/src/repositories/user_repository.rs +62 -0
- package/templates/stacks/rust-axum/src/services/auth_service.rs +50 -0
- package/templates/stacks/rust-axum/src/services/mod.rs +2 -0
- package/templates/stacks/rust-axum/src/services/user_service.rs +53 -0
- package/templates/stacks/rust-axum/tests/integration_test.rs.tera +13 -0
- package/LICENSE +0 -21
- /package/templates/ide/cursor/.cursor/commands/{generate-bugfix-design.md → dare-bugfix-design.md} +0 -0
- /package/templates/ide/cursor/.cursor/commands/{generate-feature-design.md → dare-feature-design.md} +0 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# DARE v3.0 — Quality Telemetry rake tasks
|
|
4
|
+
# Validates conformance metrics M-01 to M-04 as per dare-quality-telemetry spec
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# bundle exec rake dare:metrics # Full validation + JSON output
|
|
8
|
+
# bundle exec rake dare:metrics:quick # Exit-only (CI-friendly)
|
|
9
|
+
# bundle exec rake dare:openapi # Regenerate OpenAPI spec
|
|
10
|
+
#
|
|
11
|
+
# CI integration: add `bundle exec rake dare:metrics` to your CI pipeline.
|
|
12
|
+
# The task exits with code 1 if any metric fails.
|
|
13
|
+
|
|
14
|
+
namespace :dare do
|
|
15
|
+
# ── Main metrics validation task ─────────────────────────────────────────
|
|
16
|
+
desc "Validate DARE conformance metrics M-01 to M-04 and output JSON report"
|
|
17
|
+
task metrics: :environment do
|
|
18
|
+
require "json"
|
|
19
|
+
|
|
20
|
+
results = {
|
|
21
|
+
timestamp: Time.now.iso8601,
|
|
22
|
+
commit: git_commit_sha,
|
|
23
|
+
stack: "ruby-rails-8",
|
|
24
|
+
dare_version: "3.0",
|
|
25
|
+
metrics: {}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# M-01: llms.txt exists and is non-empty
|
|
29
|
+
llms_txt_path = Rails.root.join("llms.txt")
|
|
30
|
+
llms_txt_valid = llms_txt_path.exist? && llms_txt_path.size > 0
|
|
31
|
+
results[:metrics]["M-01"] = {
|
|
32
|
+
pass: llms_txt_valid,
|
|
33
|
+
description: "Project has valid llms.txt",
|
|
34
|
+
details: llms_txt_valid ? "llms.txt found (#{llms_txt_path.size} bytes)" : "llms.txt missing or empty"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
# M-02: OpenAPI spec exists and is valid JSON
|
|
38
|
+
openapi_path = Rails.root.join("public", "openapi.json")
|
|
39
|
+
openapi_valid = begin
|
|
40
|
+
openapi_path.exist? && JSON.parse(openapi_path.read).is_a?(Hash)
|
|
41
|
+
rescue JSON::ParserError
|
|
42
|
+
false
|
|
43
|
+
end
|
|
44
|
+
results[:metrics]["M-02"] = {
|
|
45
|
+
pass: openapi_valid,
|
|
46
|
+
description: "All endpoints have OpenAPI documentation",
|
|
47
|
+
details: openapi_valid ? "public/openapi.json found and valid" : "public/openapi.json missing or invalid JSON"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# M-03: CLI --json support (rails --help or dare:metrics itself)
|
|
51
|
+
# The DARE rails stack exposes JSON output from rake dare:metrics
|
|
52
|
+
cli_json_support = true # This task itself emits JSON — M-03 is satisfied
|
|
53
|
+
results[:metrics]["M-03"] = {
|
|
54
|
+
pass: cli_json_support,
|
|
55
|
+
description: "CLI supports --json output",
|
|
56
|
+
details: "rake dare:metrics emits JSON via STDOUT. Pass DARE_JSON=1 for machine-readable only."
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
# M-04: Rate limiting configured (rack-attack initializer present)
|
|
60
|
+
rack_attack_path = Rails.root.join("config", "initializers", "rack_attack.rb")
|
|
61
|
+
rate_limit_configured = rack_attack_path.exist?
|
|
62
|
+
results[:metrics]["M-04"] = {
|
|
63
|
+
pass: rate_limit_configured,
|
|
64
|
+
description: "100% of public endpoints have rate limit configured",
|
|
65
|
+
details: rate_limit_configured ? "rack_attack.rb initializer found" : "config/initializers/rack_attack.rb missing"
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
# ── Summary ─────────────────────────────────────────────────────────────
|
|
69
|
+
all_passed = results[:metrics].all? { |_, m| m[:pass] }
|
|
70
|
+
passed_count = results[:metrics].count { |_, m| m[:pass] }
|
|
71
|
+
total_count = results[:metrics].size
|
|
72
|
+
|
|
73
|
+
results[:summary] = {
|
|
74
|
+
passed: passed_count,
|
|
75
|
+
total: total_count,
|
|
76
|
+
all_pass: all_passed,
|
|
77
|
+
score: "#{(passed_count.to_f / total_count * 100).round(1)}%"
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# ── Output ───────────────────────────────────────────────────────────────
|
|
81
|
+
json_output = JSON.pretty_generate(results)
|
|
82
|
+
puts json_output
|
|
83
|
+
|
|
84
|
+
# Save to tmp/dare_metrics.json
|
|
85
|
+
tmp_dir = Rails.root.join("tmp")
|
|
86
|
+
FileUtils.mkdir_p(tmp_dir)
|
|
87
|
+
File.write(Rails.root.join("tmp", "dare_metrics.json"), json_output)
|
|
88
|
+
$stderr.puts "\n[DARE] Metrics saved to tmp/dare_metrics.json" unless ENV["DARE_JSON"]
|
|
89
|
+
|
|
90
|
+
unless all_passed
|
|
91
|
+
$stderr.puts "\n[DARE] FAILED: #{total_count - passed_count} metric(s) not passing.\n"
|
|
92
|
+
$stderr.puts results[:metrics].select { |_, m| !m[:pass] }.map { |k, m| " #{k}: #{m[:details]}" }.join("\n")
|
|
93
|
+
exit!(1)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
$stderr.puts "\n[DARE] All #{total_count} metrics passed (#{results[:summary][:score]})\n" unless ENV["DARE_JSON"]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# ── Quick check for CI pipelines ─────────────────────────────────────────
|
|
100
|
+
namespace :metrics do
|
|
101
|
+
desc "Quick DARE metrics check (silent — exit code only)"
|
|
102
|
+
task quick: :environment do
|
|
103
|
+
ENV["DARE_JSON"] = "1"
|
|
104
|
+
Rake::Task["dare:metrics"].invoke
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# ── OpenAPI regeneration ──────────────────────────────────────────────────
|
|
109
|
+
desc "Regenerate public/openapi.json from rswag specs"
|
|
110
|
+
task openapi: :environment do
|
|
111
|
+
puts "[DARE] Regenerating OpenAPI spec via rswag..."
|
|
112
|
+
|
|
113
|
+
# rswag generates the spec when you run rswag:specs:swaggerize
|
|
114
|
+
# This is a convenience wrapper
|
|
115
|
+
Rake::Task["rswag:specs:swaggerize"].invoke if Rake::Task.task_defined?("rswag:specs:swaggerize")
|
|
116
|
+
|
|
117
|
+
openapi_path = Rails.root.join("public", "openapi.json")
|
|
118
|
+
if openapi_path.exist?
|
|
119
|
+
puts "[DARE] OpenAPI spec generated: #{openapi_path}"
|
|
120
|
+
else
|
|
121
|
+
warn "[DARE] WARNING: public/openapi.json not found after swaggerize."
|
|
122
|
+
warn "[DARE] Run: bundle exec rspec spec/api/ to generate it."
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# ── Validate layered design ───────────────────────────────────────────────
|
|
127
|
+
desc "Validate DARE layered design directory structure"
|
|
128
|
+
task validate_structure: :environment do
|
|
129
|
+
required_dirs = %w[
|
|
130
|
+
app/handlers
|
|
131
|
+
app/services
|
|
132
|
+
app/repositories
|
|
133
|
+
app/models
|
|
134
|
+
app/presenters
|
|
135
|
+
app/llm/providers
|
|
136
|
+
app/llm/prompts
|
|
137
|
+
app/llm/validators
|
|
138
|
+
app/channels
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
missing = required_dirs.reject { |d| Rails.root.join(d).exist? }
|
|
142
|
+
|
|
143
|
+
if missing.any?
|
|
144
|
+
warn "[DARE] Missing directories:"
|
|
145
|
+
missing.each { |d| warn " - #{d}" }
|
|
146
|
+
exit!(1)
|
|
147
|
+
else
|
|
148
|
+
puts "[DARE] Layered design structure OK (#{required_dirs.size} directories)"
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
private
|
|
153
|
+
|
|
154
|
+
def git_commit_sha
|
|
155
|
+
`git rev-parse --short HEAD 2>/dev/null`.strip.presence || "unknown"
|
|
156
|
+
rescue StandardError
|
|
157
|
+
"unknown"
|
|
158
|
+
end
|
|
159
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# llms.txt — Project Context for AI Agents
|
|
2
|
+
# Generated by DARE v3.0 — ruby-rails-8 stack
|
|
3
|
+
# App: <%= app_name %>
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
Rails 8 application built with DARE v3.0 methodology.
|
|
7
|
+
Stack: ruby-rails-8 | Layered Design | OpenAPI | LLM integration | Action Cable
|
|
8
|
+
|
|
9
|
+
## Tech Stack
|
|
10
|
+
- Language: Ruby 3.3+
|
|
11
|
+
- Framework: Rails 8.0+ (Omakase)
|
|
12
|
+
- Database: PostgreSQL 14+
|
|
13
|
+
- Real-time: Action Cable + Redis
|
|
14
|
+
- Background: Solid Queue
|
|
15
|
+
- Cache: Solid Cache + Redis
|
|
16
|
+
- Deploy: Kamal
|
|
17
|
+
|
|
18
|
+
## Architecture (Layered Design)
|
|
19
|
+
- app/handlers/ — HTTP handlers (thin controllers — only HTTP concerns)
|
|
20
|
+
- app/services/ — Business logic (one class per operation, pure Ruby)
|
|
21
|
+
- app/repositories/ — Data access (interface + ActiveRecord implementation)
|
|
22
|
+
- app/models/ — Domain objects (no callbacks, no fat model)
|
|
23
|
+
- app/presenters/ — Serializers (Model → JSON, RFC 7807 errors)
|
|
24
|
+
- app/llm/ — LLM patterns (providers, prompts, validators, cache)
|
|
25
|
+
- app/channels/ — Real-time (Action Cable, authorized subscriptions)
|
|
26
|
+
- app/jobs/ — Background jobs (Solid Queue)
|
|
27
|
+
|
|
28
|
+
## Key Conventions
|
|
29
|
+
- Controllers NEVER call Repository or contain business logic
|
|
30
|
+
- Services are plain Ruby objects injected with dependencies
|
|
31
|
+
- Repositories abstract ActiveRecord; services never call AR directly
|
|
32
|
+
- Errors always formatted as RFC 7807 Problem Details
|
|
33
|
+
- Every endpoint documented via rswag (OpenAPI auto-generated from specs)
|
|
34
|
+
|
|
35
|
+
## Key Endpoints
|
|
36
|
+
- GET /openapi.json — OpenAPI spec (auto-generated by rswag)
|
|
37
|
+
- GET /api-docs — Swagger UI
|
|
38
|
+
- POST /api/users — Create user (example)
|
|
39
|
+
- GET /api/users/:id — Show user (example)
|
|
40
|
+
|
|
41
|
+
## Getting Started
|
|
42
|
+
bundle install
|
|
43
|
+
bin/rails db:create db:migrate
|
|
44
|
+
bin/rails server
|
|
45
|
+
# OR with Kamal:
|
|
46
|
+
kamal setup && kamal deploy
|
|
47
|
+
|
|
48
|
+
## Rate Limits
|
|
49
|
+
- Public endpoints: 100 req/min per IP (rack-attack)
|
|
50
|
+
- Auth endpoints: 10 req/min per IP
|
|
51
|
+
- LLM endpoints: 20 req/min per user
|
|
52
|
+
|
|
53
|
+
## For AI Agents
|
|
54
|
+
- OpenAPI spec: GET /openapi.json
|
|
55
|
+
- DARE metrics: bundle exec rake dare:metrics
|
|
56
|
+
- Test suite: bundle exec rspec
|
|
57
|
+
- Lint: bundle exec rubocop
|
|
58
|
+
- Rails help: bin/rails --help
|
|
59
|
+
- DARE manifest: .dare/skills.yml
|
|
60
|
+
|
|
61
|
+
## Directory Guide
|
|
62
|
+
- New feature? Add: handler → service → repository → model → presenter → spec
|
|
63
|
+
- New LLM feature? Add provider/prompt/validator in app/llm/
|
|
64
|
+
- New real-time event? Add channel in app/channels/ + realtime_service.rb broadcast
|
|
65
|
+
- New background job? Add in app/jobs/ using Solid Queue
|
|
66
|
+
|
|
67
|
+
## Generated by
|
|
68
|
+
DARE Method v3.0 — https://github.com/dewtech-technologies/dare-method
|
|
69
|
+
Stack: ruby-rails-8
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# DARE v3.0 — rswag OpenAPI spec for Summarize Documents API
|
|
4
|
+
# M-02: running `rake rswag:specs:swaggerize` generates public/openapi.json from this
|
|
5
|
+
require "swagger_helper"
|
|
6
|
+
|
|
7
|
+
RSpec.describe "Summarize Documents API", type: :request do
|
|
8
|
+
path "/api/v1/documents/{id}/summarize" do
|
|
9
|
+
parameter name: :id, in: :path, type: :string, description: "Document ID"
|
|
10
|
+
|
|
11
|
+
post "Summarize a document with LLM" do
|
|
12
|
+
tags "Documents"
|
|
13
|
+
produces "application/json"
|
|
14
|
+
security [{ bearerAuth: [] }]
|
|
15
|
+
description <<~DESC
|
|
16
|
+
Summarizes the document identified by :id using the configured LLM provider.
|
|
17
|
+
Returns the generated summary and the document ID on success.
|
|
18
|
+
RFC 7807 Problem Details on errors (D-006).
|
|
19
|
+
DESC
|
|
20
|
+
|
|
21
|
+
response "200", "Document summarized successfully" do
|
|
22
|
+
schema type: :object,
|
|
23
|
+
required: %w[summary document_id],
|
|
24
|
+
properties: {
|
|
25
|
+
summary: { type: :string, example: "This document discusses..." },
|
|
26
|
+
document_id: { type: :string, example: "doc-abc-123" }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let(:id) { create(:document, content: "Long content to summarize.").id }
|
|
30
|
+
run_test!
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
response "401", "Unauthorized — missing or invalid authentication token" do
|
|
34
|
+
schema "$ref" => "#/components/schemas/ProblemDetails"
|
|
35
|
+
|
|
36
|
+
let(:id) { "any-id" }
|
|
37
|
+
# No auth header provided
|
|
38
|
+
run_test!
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
response "404", "Document not found" do
|
|
42
|
+
schema "$ref" => "#/components/schemas/ProblemDetails"
|
|
43
|
+
|
|
44
|
+
let(:id) { "non-existent-document-id" }
|
|
45
|
+
run_test!
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
response "422", "Summarization failed (LLM returned empty result)" do
|
|
49
|
+
schema "$ref" => "#/components/schemas/ProblemDetails"
|
|
50
|
+
|
|
51
|
+
let(:id) { create(:document, content: "").id }
|
|
52
|
+
run_test!
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# DARE v3.0 — rswag OpenAPI spec for Users API
|
|
4
|
+
# M-02: running `rake rswag:specs:swaggerize` generates public/openapi.json from this
|
|
5
|
+
require "swagger_helper"
|
|
6
|
+
|
|
7
|
+
RSpec.describe "Users API", type: :request do
|
|
8
|
+
path "/api/users" do
|
|
9
|
+
post "Create a user" do
|
|
10
|
+
tags "Users"
|
|
11
|
+
consumes "application/json"
|
|
12
|
+
produces "application/json"
|
|
13
|
+
description "Creates a new user. Returns 201 on success, 409 if email already taken."
|
|
14
|
+
|
|
15
|
+
parameter name: :user, in: :body, schema: {
|
|
16
|
+
type: :object,
|
|
17
|
+
required: %w[email name],
|
|
18
|
+
properties: {
|
|
19
|
+
email: { type: :string, example: "alice@example.com" },
|
|
20
|
+
name: { type: :string, example: "Alice" }
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
response "201", "User created successfully" do
|
|
25
|
+
let(:user) { { email: "new@example.com", name: "New User" } }
|
|
26
|
+
run_test!
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
response "409", "Email already taken" do
|
|
30
|
+
schema "$ref" => "#/components/schemas/ProblemDetails"
|
|
31
|
+
let(:user) { { email: create(:user).email, name: "Dup" } }
|
|
32
|
+
run_test!
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
response "400", "Missing required parameters" do
|
|
36
|
+
schema "$ref" => "#/components/schemas/ProblemDetails"
|
|
37
|
+
let(:user) { {} }
|
|
38
|
+
run_test!
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
get "List active users" do
|
|
43
|
+
tags "Users"
|
|
44
|
+
produces "application/json"
|
|
45
|
+
|
|
46
|
+
response "200", "Users listed" do
|
|
47
|
+
before { create_list(:user, 3) }
|
|
48
|
+
run_test!
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
path "/api/users/{id}" do
|
|
54
|
+
parameter name: :id, in: :path, type: :integer
|
|
55
|
+
|
|
56
|
+
get "Show a user" do
|
|
57
|
+
tags "Users"
|
|
58
|
+
produces "application/json"
|
|
59
|
+
|
|
60
|
+
response "200", "User found" do
|
|
61
|
+
let(:id) { create(:user).id }
|
|
62
|
+
run_test!
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
response "404", "User not found" do
|
|
66
|
+
schema "$ref" => "#/components/schemas/ProblemDetails"
|
|
67
|
+
let(:id) { 99_999 }
|
|
68
|
+
run_test!
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# DARE v3.0 — DareUpdatesChannel spec
|
|
4
|
+
# Convention (ADR-06): tests auth and subscription behavior
|
|
5
|
+
# Verifies that document.summarized events arrive on the correct channel
|
|
6
|
+
require "rails_helper"
|
|
7
|
+
|
|
8
|
+
RSpec.describe DareUpdatesChannel, type: :channel do
|
|
9
|
+
let(:user) { create(:user) }
|
|
10
|
+
|
|
11
|
+
describe "#subscribed" do
|
|
12
|
+
context "when user is authenticated" do
|
|
13
|
+
before do
|
|
14
|
+
stub_connection current_user: user
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "subscribes successfully" do
|
|
18
|
+
subscribe
|
|
19
|
+
|
|
20
|
+
expect(subscription).to be_confirmed
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "streams from the user-scoped dare_updates channel" do
|
|
24
|
+
subscribe
|
|
25
|
+
|
|
26
|
+
expect(streams).to include("dare_updates:#{user.id}")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context "when user is not authenticated" do
|
|
31
|
+
before do
|
|
32
|
+
stub_connection current_user: nil
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "rejects the subscription" do
|
|
36
|
+
subscribe
|
|
37
|
+
|
|
38
|
+
expect(subscription).to be_rejected
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe "document.summarized event delivery" do
|
|
44
|
+
before do
|
|
45
|
+
stub_connection current_user: user
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "delivers document.summarized payload to subscribed user" do
|
|
49
|
+
subscribe
|
|
50
|
+
|
|
51
|
+
expect {
|
|
52
|
+
ActionCable.server.broadcast(
|
|
53
|
+
"dare_updates:#{user.id}",
|
|
54
|
+
{ type: "document.summarized", data: { document_id: "doc-1", summary_length: 120 } }
|
|
55
|
+
)
|
|
56
|
+
}.to have_broadcasted_to("dare_updates:#{user.id}").with(
|
|
57
|
+
hash_including(type: "document.summarized")
|
|
58
|
+
)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# DARE v3.0 — UserUpdatesChannel spec
|
|
4
|
+
# Convention (ADR-06): tests auth and subscription behavior
|
|
5
|
+
require "rails_helper"
|
|
6
|
+
|
|
7
|
+
RSpec.describe UserUpdatesChannel, type: :channel do
|
|
8
|
+
let(:user) { create(:user) }
|
|
9
|
+
|
|
10
|
+
describe "#subscribed" do
|
|
11
|
+
context "when user is authenticated and subscribing to their own updates" do
|
|
12
|
+
before do
|
|
13
|
+
stub_connection current_user: user
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "subscribes successfully" do
|
|
17
|
+
subscribe user_id: user.id
|
|
18
|
+
|
|
19
|
+
expect(subscription).to be_confirmed
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "streams for the user" do
|
|
23
|
+
subscribe user_id: user.id
|
|
24
|
+
|
|
25
|
+
expect(streams).to include("user_updates:#{user.id}")
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
context "when user tries to subscribe to another user's updates without permission" do
|
|
30
|
+
let(:other_user) { create(:user) }
|
|
31
|
+
|
|
32
|
+
before do
|
|
33
|
+
stub_connection current_user: user
|
|
34
|
+
allow(user).to receive(:can_view?).with(other_user.id).and_return(false)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "rejects the subscription" do
|
|
38
|
+
subscribe user_id: other_user.id
|
|
39
|
+
|
|
40
|
+
expect(subscription).to be_rejected
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context "when user is not authenticated" do
|
|
45
|
+
before do
|
|
46
|
+
stub_connection current_user: nil
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "rejects the subscription" do
|
|
50
|
+
subscribe user_id: user.id
|
|
51
|
+
|
|
52
|
+
expect(subscription).to be_rejected
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# DARE v3.0 — FactoryBot factories
|
|
4
|
+
# Convention: no fixtures YAML; FactoryBot only
|
|
5
|
+
|
|
6
|
+
FactoryBot.define do
|
|
7
|
+
factory :user do
|
|
8
|
+
sequence(:email) { |n| "user#{n}@example.com" }
|
|
9
|
+
name { Faker::Name.name }
|
|
10
|
+
active { true }
|
|
11
|
+
|
|
12
|
+
# Trait: admin user
|
|
13
|
+
trait :admin do
|
|
14
|
+
admin { true }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Trait: inactive user
|
|
18
|
+
trait :inactive do
|
|
19
|
+
active { false }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Trait: with all optional fields
|
|
23
|
+
trait :complete do
|
|
24
|
+
last_active_at { 1.day.ago }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# DARE v3.0 — UsersHandler spec
|
|
4
|
+
# Convention (ADR-06): request specs test HTTP contract
|
|
5
|
+
require "rails_helper"
|
|
6
|
+
|
|
7
|
+
RSpec.describe "Users API", type: :request do
|
|
8
|
+
let(:user) { create(:user) }
|
|
9
|
+
let(:valid_params) { { user: { email: "bob@example.com", name: "Bob" } } }
|
|
10
|
+
|
|
11
|
+
describe "GET /api/users/:id" do
|
|
12
|
+
context "when user exists" do
|
|
13
|
+
it "returns 200 with user JSON" do
|
|
14
|
+
get "/api/users/#{user.id}"
|
|
15
|
+
|
|
16
|
+
expect(response).to have_http_status(:ok)
|
|
17
|
+
json = JSON.parse(response.body)
|
|
18
|
+
expect(json["email"]).to eq user.email
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "when user does not exist" do
|
|
23
|
+
it "returns 404 Problem Details" do
|
|
24
|
+
get "/api/users/99999"
|
|
25
|
+
|
|
26
|
+
expect(response).to have_http_status(:not_found)
|
|
27
|
+
json = JSON.parse(response.body)
|
|
28
|
+
expect(json["status"]).to eq 404
|
|
29
|
+
expect(json["title"]).to be_present
|
|
30
|
+
expect(response.content_type).to include("application/problem+json")
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe "POST /api/users" do
|
|
36
|
+
context "with valid params" do
|
|
37
|
+
it "returns 201 Created" do
|
|
38
|
+
post "/api/users", params: valid_params, as: :json
|
|
39
|
+
|
|
40
|
+
expect(response).to have_http_status(:created)
|
|
41
|
+
json = JSON.parse(response.body)
|
|
42
|
+
expect(json["email"]).to eq "bob@example.com"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context "with duplicate email" do
|
|
47
|
+
before { create(:user, email: "bob@example.com") }
|
|
48
|
+
|
|
49
|
+
it "returns 409 Conflict with Problem Details" do
|
|
50
|
+
post "/api/users", params: valid_params, as: :json
|
|
51
|
+
|
|
52
|
+
expect(response).to have_http_status(:conflict)
|
|
53
|
+
json = JSON.parse(response.body)
|
|
54
|
+
expect(json["status"]).to eq 409
|
|
55
|
+
expect(response.content_type).to include("application/problem+json")
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
context "with missing required params" do
|
|
60
|
+
it "returns 400 Bad Request" do
|
|
61
|
+
post "/api/users", params: { user: {} }, as: :json
|
|
62
|
+
|
|
63
|
+
expect(response).to have_http_status(:bad_request)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
describe "PATCH /api/users/:id" do
|
|
69
|
+
it "returns 200 with updated user" do
|
|
70
|
+
patch "/api/users/#{user.id}",
|
|
71
|
+
params: { user: { name: "Updated Name" } },
|
|
72
|
+
as: :json,
|
|
73
|
+
headers: { "Authorization" => "Bearer test-token" }
|
|
74
|
+
|
|
75
|
+
# Note: authentication stub needed — wire up in test support
|
|
76
|
+
expect(response).not_to have_http_status(:internal_server_error)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
describe "DELETE /api/users/:id" do
|
|
81
|
+
it "returns 204 No Content" do
|
|
82
|
+
delete "/api/users/#{user.id}",
|
|
83
|
+
headers: { "Authorization" => "Bearer test-token" }
|
|
84
|
+
|
|
85
|
+
expect(response).not_to have_http_status(:internal_server_error)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# DARE v3.0 — RSpec rails_helper
|
|
4
|
+
|
|
5
|
+
ENV["RAILS_ENV"] ||= "test"
|
|
6
|
+
require_relative "../config/environment"
|
|
7
|
+
require "rspec/rails"
|
|
8
|
+
|
|
9
|
+
# Require support files
|
|
10
|
+
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
|
|
11
|
+
|
|
12
|
+
# Prevent database truncation if the environment is production
|
|
13
|
+
abort("The Rails environment is running in production mode!") if Rails.env.production?
|
|
14
|
+
|
|
15
|
+
RSpec.configure do |config|
|
|
16
|
+
config.fixture_paths = ["#{::Rails.root}/spec/fixtures"]
|
|
17
|
+
config.use_transactional_fixtures = true
|
|
18
|
+
config.infer_spec_type_from_file_location!
|
|
19
|
+
config.filter_rails_from_backtrace!
|
|
20
|
+
|
|
21
|
+
# FactoryBot
|
|
22
|
+
config.include FactoryBot::Syntax::Methods
|
|
23
|
+
|
|
24
|
+
# Shoulda Matchers
|
|
25
|
+
Shoulda::Matchers.configure do |shoulda|
|
|
26
|
+
shoulda.integrate do |with|
|
|
27
|
+
with.test_framework :rspec
|
|
28
|
+
with.library :rails
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|