spoonfeeder 0.1.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 +249 -0
- package/dist/generator/ai-context-assembler.d.ts +4 -0
- package/dist/generator/ai-context-assembler.js +52 -0
- package/dist/generator/ai-context-assembler.js.map +1 -0
- package/dist/generator/env-merger.d.ts +3 -0
- package/dist/generator/env-merger.js +16 -0
- package/dist/generator/env-merger.js.map +1 -0
- package/dist/generator/generator.d.ts +3 -0
- package/dist/generator/generator.js +253 -0
- package/dist/generator/generator.js.map +1 -0
- package/dist/generator/package-json-merger.d.ts +6 -0
- package/dist/generator/package-json-merger.js +29 -0
- package/dist/generator/package-json-merger.js.map +1 -0
- package/dist/generator/post-generate.d.ts +1 -0
- package/dist/generator/post-generate.js +28 -0
- package/dist/generator/post-generate.js.map +1 -0
- package/dist/generator/template-engine.d.ts +4 -0
- package/dist/generator/template-engine.js +20 -0
- package/dist/generator/template-engine.js.map +1 -0
- package/dist/generators/add-recipe/generator.d.ts +3 -0
- package/dist/generators/add-recipe/generator.js +153 -0
- package/dist/generators/add-recipe/generator.js.map +1 -0
- package/dist/generators/list-recipes/generator.d.ts +3 -0
- package/dist/generators/list-recipes/generator.js +58 -0
- package/dist/generators/list-recipes/generator.js.map +1 -0
- package/dist/generators/migrate-recipe/generator.d.ts +9 -0
- package/dist/generators/migrate-recipe/generator.js +90 -0
- package/dist/generators/migrate-recipe/generator.js.map +1 -0
- package/dist/generators/migrate-recipe/migration-guidance.d.ts +1 -0
- package/dist/generators/migrate-recipe/migration-guidance.js +159 -0
- package/dist/generators/migrate-recipe/migration-guidance.js.map +1 -0
- package/dist/generators/remove-recipe/generator.d.ts +3 -0
- package/dist/generators/remove-recipe/generator.js +176 -0
- package/dist/generators/remove-recipe/generator.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/add-ons.d.ts +3 -0
- package/dist/prompts/add-ons.js +29 -0
- package/dist/prompts/add-ons.js.map +1 -0
- package/dist/prompts/ci-cd.d.ts +2 -0
- package/dist/prompts/ci-cd.js +19 -0
- package/dist/prompts/ci-cd.js.map +1 -0
- package/dist/prompts/cloud-provider.d.ts +2 -0
- package/dist/prompts/cloud-provider.js +18 -0
- package/dist/prompts/cloud-provider.js.map +1 -0
- package/dist/prompts/confirmation.d.ts +2 -0
- package/dist/prompts/confirmation.js +29 -0
- package/dist/prompts/confirmation.js.map +1 -0
- package/dist/prompts/deployment.d.ts +2 -0
- package/dist/prompts/deployment.js +20 -0
- package/dist/prompts/deployment.js.map +1 -0
- package/dist/prompts/frontend.d.ts +2 -0
- package/dist/prompts/frontend.js +18 -0
- package/dist/prompts/frontend.js.map +1 -0
- package/dist/prompts/project-name.d.ts +5 -0
- package/dist/prompts/project-name.js +34 -0
- package/dist/prompts/project-name.js.map +1 -0
- package/dist/prompts/project-type.d.ts +2 -0
- package/dist/prompts/project-type.js +22 -0
- package/dist/prompts/project-type.js.map +1 -0
- package/dist/prompts/run-all.d.ts +3 -0
- package/dist/prompts/run-all.js +83 -0
- package/dist/prompts/run-all.js.map +1 -0
- package/dist/prompts/transport.d.ts +2 -0
- package/dist/prompts/transport.js +22 -0
- package/dist/prompts/transport.js.map +1 -0
- package/dist/recipes/definitions.d.ts +2 -0
- package/dist/recipes/definitions.js +3647 -0
- package/dist/recipes/definitions.js.map +1 -0
- package/dist/recipes/recipe.interface.d.ts +8 -0
- package/dist/recipes/recipe.interface.js +2 -0
- package/dist/recipes/recipe.interface.js.map +1 -0
- package/dist/recipes/registry.d.ts +9 -0
- package/dist/recipes/registry.js +23 -0
- package/dist/recipes/registry.js.map +1 -0
- package/dist/types.d.ts +70 -0
- package/dist/types.js +152 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/ai-context-updater.d.ts +6 -0
- package/dist/utils/ai-context-updater.js +50 -0
- package/dist/utils/ai-context-updater.js.map +1 -0
- package/dist/utils/dependency-checker.d.ts +14 -0
- package/dist/utils/dependency-checker.js +27 -0
- package/dist/utils/dependency-checker.js.map +1 -0
- package/dist/utils/env-updater.d.ts +7 -0
- package/dist/utils/env-updater.js +35 -0
- package/dist/utils/env-updater.js.map +1 -0
- package/dist/utils/main-ts-updater.d.ts +37 -0
- package/dist/utils/main-ts-updater.js +144 -0
- package/dist/utils/main-ts-updater.js.map +1 -0
- package/dist/utils/module-updater.d.ts +26 -0
- package/dist/utils/module-updater.js +167 -0
- package/dist/utils/module-updater.js.map +1 -0
- package/dist/utils/recipe-manifest.d.ts +24 -0
- package/dist/utils/recipe-manifest.js +45 -0
- package/dist/utils/recipe-manifest.js.map +1 -0
- package/dist/validation/config-validator.d.ts +13 -0
- package/dist/validation/config-validator.js +50 -0
- package/dist/validation/config-validator.js.map +1 -0
- package/dist/validation/conflict-detector.d.ts +7 -0
- package/dist/validation/conflict-detector.js +37 -0
- package/dist/validation/conflict-detector.js.map +1 -0
- package/generators.json +24 -0
- package/package.json +78 -0
- package/src/generators/add-recipe/schema.json +21 -0
- package/src/generators/list-recipes/schema.json +18 -0
- package/src/generators/migrate-recipe/schema.json +20 -0
- package/src/generators/remove-recipe/schema.json +21 -0
- package/templates/base/.env.example.ejs +3 -0
- package/templates/base/README.md.ejs +20 -0
- package/templates/base/SECURITY.md +36 -0
- package/templates/base/commitlint.config.js +15 -0
- package/templates/base/docs/adr/000-template.md +45 -0
- package/templates/base/docs/adr/001-framework-selection.md +54 -0
- package/templates/base/docs/adr/002-error-handling-strategy.md +36 -0
- package/templates/base/docs/adr/003-database-strategy.md +40 -0
- package/templates/base/docs/adr/004-authentication-architecture.md +44 -0
- package/templates/base/docs/adr/005-deployment-strategy.md +40 -0
- package/templates/base/docs/adr/006-testing-strategy.md +41 -0
- package/templates/base/docs/adr/007-scaffolder-architecture.md +64 -0
- package/templates/base/docs/adr/008-recipe-system.md +47 -0
- package/templates/base/docs/adr/009-standards-compliance.md +54 -0
- package/templates/base/docs/adr/010-ai-context-generation.md +44 -0
- package/templates/base/docs/adr/011-package-versioning.md +44 -0
- package/templates/base/docs/adr/012-monorepo-strategy.md +54 -0
- package/templates/base/docs/adr/013-http-adapter.md +63 -0
- package/templates/base/docs/adr/014-build-toolchain.md +61 -0
- package/templates/base/docs/adr/015-cloud-provider-strategy.md +49 -0
- package/templates/base/docs/adr/016-ci-cd-pipeline-strategy.md +52 -0
- package/templates/base/docs/adr/017-logging-strategy.md +63 -0
- package/templates/base/docs/adr/018-security-architecture.md +61 -0
- package/templates/base/docs/adr/019-project-type-design.md +61 -0
- package/templates/base/docs/adr/020-frontend-framework-support.md +57 -0
- package/templates/base/docs/adr/021-observability-strategy.md +68 -0
- package/templates/base/docs/adr/022-api-design-patterns.md +64 -0
- package/templates/base/docs/adr/023-error-hierarchy.md +54 -0
- package/templates/base/docs/adr/024-request-context-pattern.md +57 -0
- package/templates/base/docs/adr/025-data-patterns.md +58 -0
- package/templates/base/docs/adr/026-migration-strategy.md +57 -0
- package/templates/base/docs/adr/027-dependency-management.md +60 -0
- package/templates/base/docs/adr/028-code-quality-toolchain.md +60 -0
- package/templates/base/docs/adr/029-admin-panel.md +53 -0
- package/templates/base/docs/adr/030-performance-patterns.md +60 -0
- package/templates/base/docs/adr/031-nx-generators-roadmap.md +73 -0
- package/templates/base/docs/runbooks/000-template.md +78 -0
- package/templates/base/docs/sla-slo.md +36 -0
- package/templates/base/dot-editorconfig +12 -0
- package/templates/base/dot-github/ISSUE_TEMPLATE/bug_report.md +33 -0
- package/templates/base/dot-github/ISSUE_TEMPLATE/feature_request.md +21 -0
- package/templates/base/dot-github/pull_request_template.md +32 -0
- package/templates/base/dot-gitignore +28 -0
- package/templates/base/dot-husky/commit-msg +1 -0
- package/templates/base/dot-husky/pre-commit +1 -0
- package/templates/base/dot-husky/pre-push +2 -0
- package/templates/base/dot-npmrc +1 -0
- package/templates/base/dot-nvmrc +1 -0
- package/templates/base/dot-prettierrc +8 -0
- package/templates/base/eslint.config.mjs +35 -0
- package/templates/base/jest.config.ts +56 -0
- package/templates/base/nest-cli.json.ejs +10 -0
- package/templates/base/nx.json +3 -0
- package/templates/base/package.json.ejs +78 -0
- package/templates/base/src/app/modules/.gitkeep +0 -0
- package/templates/base/src/config/.gitkeep +0 -0
- package/templates/base/src/infrastructure/database/entities/.gitkeep +0 -0
- package/templates/base/src/infrastructure/database/migrations/.gitkeep +0 -0
- package/templates/base/src/infrastructure/database/repositories/.gitkeep +0 -0
- package/templates/base/src/infrastructure/http/.gitkeep +0 -0
- package/templates/base/src/infrastructure/notifications/.gitkeep +0 -0
- package/templates/base/src/infrastructure/queue/.gitkeep +0 -0
- package/templates/base/src/infrastructure/storage/.gitkeep +0 -0
- package/templates/base/src/shared/constants/error-codes.constant.ts +30 -0
- package/templates/base/src/shared/constants/http.constant.ts +134 -0
- package/templates/base/src/shared/constants/index.ts +2 -0
- package/templates/base/src/shared/decorators/.gitkeep +0 -0
- package/templates/base/src/shared/decorators/api-paginated-response.decorator.ts +10 -0
- package/templates/base/src/shared/errors/application.error.ts +21 -0
- package/templates/base/src/shared/errors/forbidden.error.ts +7 -0
- package/templates/base/src/shared/errors/index.ts +6 -0
- package/templates/base/src/shared/errors/invalid-request.error.ts +7 -0
- package/templates/base/src/shared/errors/not-found.error.ts +7 -0
- package/templates/base/src/shared/errors/requester.error.ts +7 -0
- package/templates/base/src/shared/errors/validation.error.ts +7 -0
- package/templates/base/src/shared/filters/http-exception.filter.ts +139 -0
- package/templates/base/src/shared/guards/.gitkeep +0 -0
- package/templates/base/src/shared/interceptors/interfaces/.gitkeep +0 -0
- package/templates/base/src/shared/interceptors/response.interceptor.ts +22 -0
- package/templates/base/src/shared/middleware/request-timeout.middleware.ts +32 -0
- package/templates/base/src/shared/pipes/parse-uuid.pipe.ts +13 -0
- package/templates/base/src/shared/utils/index.ts +2 -0
- package/templates/base/src/shared/utils/retry.util.ts +32 -0
- package/templates/base/src/shared/utils/sleep.util.ts +3 -0
- package/templates/base/tests/e2e/app.e2e-spec.ts.ejs +25 -0
- package/templates/base/tests/factories/.gitkeep +0 -0
- package/templates/base/tests/helpers/.gitkeep +0 -0
- package/templates/base/tests/integration/.gitkeep +0 -0
- package/templates/base/tests/unit/app.module.spec.ts +11 -0
- package/templates/base/tests/unit/shared/errors/error-hierarchy.spec.ts +69 -0
- package/templates/base/tests/unit/shared/filters/http-exception.filter.spec.ts +188 -0
- package/templates/base/tests/unit/shared/interceptors/response.interceptor.spec.ts +54 -0
- package/templates/base/tests/unit/shared/pipes/parse-uuid.pipe.spec.ts +14 -0
- package/templates/base/tsconfig.build.json +4 -0
- package/templates/base/tsconfig.json.ejs +26 -0
- package/templates/project-types/aws-lambda/package-fragment.json +8 -0
- package/templates/project-types/aws-lambda/src/app.module.ts.ejs +9 -0
- package/templates/project-types/aws-lambda/src/main.ts.ejs +32 -0
- package/templates/project-types/aws-lambda/tests/unit/handler.spec.ts +7 -0
- package/templates/project-types/cli-app/package-fragment.json +8 -0
- package/templates/project-types/cli-app/src/app.module.ts.ejs +11 -0
- package/templates/project-types/cli-app/src/commands/hello.command.ts.ejs +8 -0
- package/templates/project-types/cli-app/src/main.ts.ejs +8 -0
- package/templates/project-types/cli-app/tests/unit/commands/hello.command.spec.ts +17 -0
- package/templates/project-types/full-stack/apps/api/src/app.module.ts.ejs +9 -0
- package/templates/project-types/full-stack/apps/api/src/main.ts.ejs +32 -0
- package/templates/project-types/full-stack/frontend/nextjs/.cursor/rules/nextjs.mdc +12 -0
- package/templates/project-types/full-stack/frontend/nextjs/.github/copilot-instructions.md +23 -0
- package/templates/project-types/full-stack/frontend/nextjs/CLAUDE.md +25 -0
- package/templates/project-types/full-stack/frontend/nextjs/next.config.ts +9 -0
- package/templates/project-types/full-stack/frontend/nextjs/package.json +21 -0
- package/templates/project-types/full-stack/frontend/nextjs/src/app/layout.tsx +9 -0
- package/templates/project-types/full-stack/frontend/nextjs/src/app/page.tsx +8 -0
- package/templates/project-types/full-stack/frontend/nextjs/tsconfig.json +21 -0
- package/templates/project-types/full-stack/frontend/nuxt/.cursor/rules/nuxt.mdc +14 -0
- package/templates/project-types/full-stack/frontend/nuxt/.github/copilot-instructions.md +25 -0
- package/templates/project-types/full-stack/frontend/nuxt/CLAUDE.md +25 -0
- package/templates/project-types/full-stack/frontend/nuxt/app.vue +5 -0
- package/templates/project-types/full-stack/frontend/nuxt/nuxt.config.ts +6 -0
- package/templates/project-types/full-stack/frontend/nuxt/package.json +17 -0
- package/templates/project-types/full-stack/frontend/nuxt/pages/index.vue +3 -0
- package/templates/project-types/full-stack/frontend/nuxt/tsconfig.json +1 -0
- package/templates/project-types/full-stack/frontend/sveltekit/.cursor/rules/sveltekit.mdc +13 -0
- package/templates/project-types/full-stack/frontend/sveltekit/.github/copilot-instructions.md +24 -0
- package/templates/project-types/full-stack/frontend/sveltekit/CLAUDE.md +25 -0
- package/templates/project-types/full-stack/frontend/sveltekit/package.json +17 -0
- package/templates/project-types/full-stack/frontend/sveltekit/src/app.html +5 -0
- package/templates/project-types/full-stack/frontend/sveltekit/src/routes/+page.svelte +1 -0
- package/templates/project-types/full-stack/frontend/sveltekit/svelte.config.js +5 -0
- package/templates/project-types/full-stack/frontend/sveltekit/vite.config.ts +9 -0
- package/templates/project-types/full-stack/frontend/vite-react/.cursor/rules/react.mdc +12 -0
- package/templates/project-types/full-stack/frontend/vite-react/.github/copilot-instructions.md +23 -0
- package/templates/project-types/full-stack/frontend/vite-react/CLAUDE.md +24 -0
- package/templates/project-types/full-stack/frontend/vite-react/index.html +5 -0
- package/templates/project-types/full-stack/frontend/vite-react/package.json +22 -0
- package/templates/project-types/full-stack/frontend/vite-react/src/App.tsx +8 -0
- package/templates/project-types/full-stack/frontend/vite-react/src/main.tsx +9 -0
- package/templates/project-types/full-stack/frontend/vite-react/tsconfig.json +21 -0
- package/templates/project-types/full-stack/frontend/vite-react/vite.config.ts +9 -0
- package/templates/project-types/full-stack/libs/shared-types/package.json.ejs +6 -0
- package/templates/project-types/full-stack/libs/shared-types/src/index.ts.ejs +15 -0
- package/templates/project-types/full-stack/nx.json.ejs +20 -0
- package/templates/project-types/full-stack/package-fragment.json +14 -0
- package/templates/project-types/full-stack/pnpm-workspace.yaml +3 -0
- package/templates/project-types/full-stack/tsconfig.json.ejs +27 -0
- package/templates/project-types/http-api/src/app.module.ts.ejs +9 -0
- package/templates/project-types/http-api/src/main.ts.ejs +30 -0
- package/templates/project-types/http-api/tests/e2e/health.e2e-spec.ts +23 -0
- package/templates/project-types/microservice/package-fragment.json +5 -0
- package/templates/project-types/microservice/src/app.module.ts.ejs +9 -0
- package/templates/project-types/microservice/src/main.ts.ejs +15 -0
- package/templates/project-types/microservice/tests/unit/app.module.spec.ts +9 -0
- package/templates/project-types/monorepo/README.md.ejs +33 -0
- package/templates/project-types/monorepo/apps/api/src/app.module.ts.ejs +9 -0
- package/templates/project-types/monorepo/apps/api/src/main.ts.ejs +30 -0
- package/templates/project-types/monorepo/libs/common/package.json.ejs +6 -0
- package/templates/project-types/monorepo/libs/common/src/index.ts.ejs +17 -0
- package/templates/project-types/monorepo/nx.json.ejs +20 -0
- package/templates/project-types/monorepo/package-fragment.json +13 -0
- package/templates/project-types/monorepo/pnpm-workspace.yaml +3 -0
- package/templates/project-types/monorepo/tsconfig.json.ejs +27 -0
- package/templates/project-types/scheduled-worker/package-fragment.json +5 -0
- package/templates/project-types/scheduled-worker/src/app.module.ts.ejs +13 -0
- package/templates/project-types/scheduled-worker/src/jobs/example.job.ts.ejs +12 -0
- package/templates/project-types/scheduled-worker/src/main.ts.ejs +10 -0
- package/templates/project-types/scheduled-worker/tests/unit/jobs/example.job.spec.ts +17 -0
- package/templates/recipes/adminjs/README.md +145 -0
- package/templates/recipes/adminjs/src/app/modules/admin/admin.module.ts +59 -0
- package/templates/recipes/adminjs/tests/unit/app/modules/admin/admin.module.spec.ts +22 -0
- package/templates/recipes/ai-context/README.md +11 -0
- package/templates/recipes/ai-context/claude/base.md +73 -0
- package/templates/recipes/ai-context/claude/commands/add-command.md +48 -0
- package/templates/recipes/ai-context/claude/commands/add-consumer.md +58 -0
- package/templates/recipes/ai-context/claude/commands/add-endpoint.md +69 -0
- package/templates/recipes/ai-context/claude/commands/add-job.md +42 -0
- package/templates/recipes/ai-context/claude/commands/migrate.md +69 -0
- package/templates/recipes/ai-context/copilot/base.md +71 -0
- package/templates/recipes/ai-context/cursor/auth.mdc +44 -0
- package/templates/recipes/ai-context/cursor/base.mdc +44 -0
- package/templates/recipes/ai-context/cursor/prisma.mdc +43 -0
- package/templates/recipes/ai-context/cursor/swagger.mdc +48 -0
- package/templates/recipes/ai-context/cursor/testing.mdc +58 -0
- package/templates/recipes/ai-context/cursor/typeorm.mdc +49 -0
- package/templates/recipes/api-keys/README.md +44 -0
- package/templates/recipes/api-keys/src/shared/guards/api-key.guard.ts +32 -0
- package/templates/recipes/api-keys/tests/unit/shared/guards/api-key.guard.spec.ts +40 -0
- package/templates/recipes/api-versioning/README.md +63 -0
- package/templates/recipes/audit-trail/README.md +75 -0
- package/templates/recipes/audit-trail/src/shared/decorators/auditable.decorator.ts +4 -0
- package/templates/recipes/audit-trail/src/shared/interceptors/audit.interceptor.ts +46 -0
- package/templates/recipes/audit-trail/tests/unit/shared/interceptors/audit.interceptor.spec.ts +82 -0
- package/templates/recipes/auth-flows/README.md +91 -0
- package/templates/recipes/auth-flows/src/app/modules/auth/auth.controller.ts +44 -0
- package/templates/recipes/auth-flows/src/app/modules/auth/auth.module.ts +11 -0
- package/templates/recipes/auth-flows/src/app/modules/auth/auth.service.ts +194 -0
- package/templates/recipes/auth-flows/src/app/modules/auth/dto/forgot-password.dto.ts +6 -0
- package/templates/recipes/auth-flows/src/app/modules/auth/dto/login.dto.ts +9 -0
- package/templates/recipes/auth-flows/src/app/modules/auth/dto/reset-password.dto.ts +11 -0
- package/templates/recipes/auth-flows/src/app/modules/auth/dto/signup.dto.ts +16 -0
- package/templates/recipes/auth-flows/tests/unit/app/modules/auth/auth.service.spec.ts +13 -0
- package/templates/recipes/bullmq/README.md +54 -0
- package/templates/recipes/bullmq/src/infrastructure/queue/example.processor.ts +25 -0
- package/templates/recipes/bullmq/src/infrastructure/queue/queue.module.ts +26 -0
- package/templates/recipes/bullmq/tests/unit/infrastructure/queue/example.processor.spec.ts +17 -0
- package/templates/recipes/changelog/.changelogrc.json +18 -0
- package/templates/recipes/changelog/README.md +44 -0
- package/templates/recipes/ci-cd/README.md +14 -0
- package/templates/recipes/ci-cd/aws-codepipeline/README.md +30 -0
- package/templates/recipes/ci-cd/aws-codepipeline/buildspec.yml +41 -0
- package/templates/recipes/ci-cd/azure-devops/README.md +32 -0
- package/templates/recipes/ci-cd/azure-devops/azure-pipelines.yml +79 -0
- package/templates/recipes/ci-cd/gcp-cloudbuild/README.md +64 -0
- package/templates/recipes/ci-cd/gcp-cloudbuild/cloudbuild.yaml +53 -0
- package/templates/recipes/ci-cd/github-actions/.github/workflows/cd.yml +35 -0
- package/templates/recipes/ci-cd/github-actions/.github/workflows/ci.yml +62 -0
- package/templates/recipes/ci-cd/github-actions/README.md +29 -0
- package/templates/recipes/circuit-breaker/README.md +45 -0
- package/templates/recipes/circuit-breaker/src/shared/utils/circuit-breaker.ts +100 -0
- package/templates/recipes/circuit-breaker/tests/unit/shared/utils/circuit-breaker.spec.ts +28 -0
- package/templates/recipes/cloud-aws/README.md +20 -0
- package/templates/recipes/cloud-aws/cloudfront/README.md +50 -0
- package/templates/recipes/cloud-aws/cloudfront/src/infrastructure/aws/cloudfront.module.ts +8 -0
- package/templates/recipes/cloud-aws/cloudfront/src/infrastructure/aws/cloudfront.service.ts +29 -0
- package/templates/recipes/cloud-aws/cloudwatch/README.md +40 -0
- package/templates/recipes/cloud-aws/cloudwatch/src/infrastructure/aws/cloudwatch.module.ts +8 -0
- package/templates/recipes/cloud-aws/cloudwatch/src/infrastructure/aws/cloudwatch.service.ts +40 -0
- package/templates/recipes/cloud-aws/cognito/README.md +39 -0
- package/templates/recipes/cloud-aws/cognito/src/infrastructure/aws/cognito.module.ts +8 -0
- package/templates/recipes/cloud-aws/cognito/src/infrastructure/aws/cognito.service.ts +47 -0
- package/templates/recipes/cloud-aws/dynamodb/README.md +48 -0
- package/templates/recipes/cloud-aws/dynamodb/src/infrastructure/aws/dynamodb.module.ts +8 -0
- package/templates/recipes/cloud-aws/dynamodb/src/infrastructure/aws/dynamodb.service.ts +49 -0
- package/templates/recipes/cloud-aws/elasticache/README.md +45 -0
- package/templates/recipes/cloud-aws/elasticache/src/infrastructure/aws/redis.module.ts +8 -0
- package/templates/recipes/cloud-aws/elasticache/src/infrastructure/aws/redis.service.ts +47 -0
- package/templates/recipes/cloud-aws/eventbridge/README.md +46 -0
- package/templates/recipes/cloud-aws/eventbridge/src/infrastructure/aws/eventbridge.module.ts +8 -0
- package/templates/recipes/cloud-aws/eventbridge/src/infrastructure/aws/eventbridge.service.ts +48 -0
- package/templates/recipes/cloud-aws/rds/README.md +59 -0
- package/templates/recipes/cloud-aws/s3/README.md +44 -0
- package/templates/recipes/cloud-aws/s3/src/infrastructure/aws/s3.module.ts +8 -0
- package/templates/recipes/cloud-aws/s3/src/infrastructure/aws/s3.service.ts +42 -0
- package/templates/recipes/cloud-aws/secrets-manager/README.md +38 -0
- package/templates/recipes/cloud-aws/secrets-manager/src/infrastructure/aws/secrets.module.ts +8 -0
- package/templates/recipes/cloud-aws/secrets-manager/src/infrastructure/aws/secrets.service.ts +39 -0
- package/templates/recipes/cloud-aws/sns/README.md +43 -0
- package/templates/recipes/cloud-aws/sns/src/infrastructure/aws/sns.module.ts +8 -0
- package/templates/recipes/cloud-aws/sns/src/infrastructure/aws/sns.service.ts +48 -0
- package/templates/recipes/cloud-aws/sqs/README.md +47 -0
- package/templates/recipes/cloud-aws/sqs/src/infrastructure/aws/sqs.module.ts +8 -0
- package/templates/recipes/cloud-aws/sqs/src/infrastructure/aws/sqs.service.ts +58 -0
- package/templates/recipes/cloud-aws/ssm/README.md +41 -0
- package/templates/recipes/cloud-aws/ssm/src/infrastructure/aws/ssm.module.ts +8 -0
- package/templates/recipes/cloud-aws/ssm/src/infrastructure/aws/ssm.service.ts +54 -0
- package/templates/recipes/cloud-azure/README.md +18 -0
- package/templates/recipes/cloud-azure/app-insights/README.md +50 -0
- package/templates/recipes/cloud-azure/app-insights/src/infrastructure/azure/app-insights.module.ts +11 -0
- package/templates/recipes/cloud-azure/app-insights/src/infrastructure/azure/app-insights.service.ts +38 -0
- package/templates/recipes/cloud-azure/blob-storage/README.md +49 -0
- package/templates/recipes/cloud-azure/blob-storage/src/infrastructure/azure/blob-storage.module.ts +11 -0
- package/templates/recipes/cloud-azure/blob-storage/src/infrastructure/azure/blob-storage.service.ts +64 -0
- package/templates/recipes/cloud-azure/cache/README.md +47 -0
- package/templates/recipes/cloud-azure/cache/src/infrastructure/azure/redis.module.ts +11 -0
- package/templates/recipes/cloud-azure/cache/src/infrastructure/azure/redis.service.ts +41 -0
- package/templates/recipes/cloud-azure/cosmos-db/README.md +57 -0
- package/templates/recipes/cloud-azure/cosmos-db/src/infrastructure/azure/cosmos-db.module.ts +11 -0
- package/templates/recipes/cloud-azure/cosmos-db/src/infrastructure/azure/cosmos-db.service.ts +55 -0
- package/templates/recipes/cloud-azure/entra-id/README.md +42 -0
- package/templates/recipes/cloud-azure/entra-id/src/infrastructure/azure/entra-id.module.ts +11 -0
- package/templates/recipes/cloud-azure/entra-id/src/infrastructure/azure/entra-id.service.ts +55 -0
- package/templates/recipes/cloud-azure/front-door/README.md +48 -0
- package/templates/recipes/cloud-azure/functions/README.md +48 -0
- package/templates/recipes/cloud-azure/key-vault/README.md +42 -0
- package/templates/recipes/cloud-azure/key-vault/src/infrastructure/azure/key-vault.module.ts +11 -0
- package/templates/recipes/cloud-azure/key-vault/src/infrastructure/azure/key-vault.service.ts +27 -0
- package/templates/recipes/cloud-azure/service-bus/README.md +49 -0
- package/templates/recipes/cloud-azure/service-bus/src/infrastructure/azure/service-bus.module.ts +11 -0
- package/templates/recipes/cloud-azure/service-bus/src/infrastructure/azure/service-bus.service.ts +52 -0
- package/templates/recipes/cloud-azure/sql-database/README.md +54 -0
- package/templates/recipes/cloud-gcp/README.md +18 -0
- package/templates/recipes/cloud-gcp/cloud-cdn/README.md +40 -0
- package/templates/recipes/cloud-gcp/cloud-functions/README.md +42 -0
- package/templates/recipes/cloud-gcp/cloud-logging/README.md +42 -0
- package/templates/recipes/cloud-gcp/cloud-logging/src/infrastructure/gcp/logging.module.ts +10 -0
- package/templates/recipes/cloud-gcp/cloud-logging/src/infrastructure/gcp/logging.service.ts +50 -0
- package/templates/recipes/cloud-gcp/cloud-sql/README.md +53 -0
- package/templates/recipes/cloud-gcp/cloud-storage/README.md +43 -0
- package/templates/recipes/cloud-gcp/cloud-storage/src/infrastructure/gcp/storage.module.ts +10 -0
- package/templates/recipes/cloud-gcp/cloud-storage/src/infrastructure/gcp/storage.service.ts +51 -0
- package/templates/recipes/cloud-gcp/firebase-auth/README.md +38 -0
- package/templates/recipes/cloud-gcp/firebase-auth/src/infrastructure/gcp/firebase-auth.module.ts +10 -0
- package/templates/recipes/cloud-gcp/firebase-auth/src/infrastructure/gcp/firebase-auth.service.ts +41 -0
- package/templates/recipes/cloud-gcp/firestore/README.md +46 -0
- package/templates/recipes/cloud-gcp/firestore/src/infrastructure/gcp/firestore.module.ts +10 -0
- package/templates/recipes/cloud-gcp/firestore/src/infrastructure/gcp/firestore.service.ts +44 -0
- package/templates/recipes/cloud-gcp/memorystore/README.md +44 -0
- package/templates/recipes/cloud-gcp/memorystore/src/infrastructure/gcp/redis.module.ts +10 -0
- package/templates/recipes/cloud-gcp/memorystore/src/infrastructure/gcp/redis.service.ts +54 -0
- package/templates/recipes/cloud-gcp/pubsub/README.md +43 -0
- package/templates/recipes/cloud-gcp/pubsub/src/infrastructure/gcp/pubsub.module.ts +10 -0
- package/templates/recipes/cloud-gcp/pubsub/src/infrastructure/gcp/pubsub.service.ts +60 -0
- package/templates/recipes/cloud-gcp/secret-manager/README.md +40 -0
- package/templates/recipes/cloud-gcp/secret-manager/src/infrastructure/gcp/secrets.module.ts +10 -0
- package/templates/recipes/cloud-gcp/secret-manager/src/infrastructure/gcp/secrets.service.ts +41 -0
- package/templates/recipes/config-validation/README.md +61 -0
- package/templates/recipes/config-validation/src/config/env.validation.ts +28 -0
- package/templates/recipes/config-validation/tests/unit/config/env.validation.spec.ts +34 -0
- package/templates/recipes/content-digest/README.md +28 -0
- package/templates/recipes/content-digest/src/shared/guards/content-digest.guard.ts +30 -0
- package/templates/recipes/content-digest/src/shared/interceptors/content-digest.interceptor.ts +23 -0
- package/templates/recipes/content-digest/tests/unit/shared/guards/content-digest.guard.spec.ts +56 -0
- package/templates/recipes/content-digest/tests/unit/shared/interceptors/content-digest.interceptor.spec.ts +54 -0
- package/templates/recipes/correlation-id/README.md +44 -0
- package/templates/recipes/correlation-id/src/shared/middleware/correlation-id.middleware.ts +29 -0
- package/templates/recipes/correlation-id/tests/unit/shared/middleware/correlation-id.spec.ts +5 -0
- package/templates/recipes/cors/README.md +45 -0
- package/templates/recipes/cqrs/README.md +39 -0
- package/templates/recipes/cqrs/src/shared/cqrs/example.command.ts +29 -0
- package/templates/recipes/cqrs/tests/unit/shared/cqrs/example.command.spec.ts +38 -0
- package/templates/recipes/csrf/README.md +55 -0
- package/templates/recipes/data-masking/README.md +85 -0
- package/templates/recipes/data-masking/src/shared/decorators/sensitive.decorator.ts +12 -0
- package/templates/recipes/data-masking/src/shared/utils/mask.util.ts +26 -0
- package/templates/recipes/data-masking/tests/unit/shared/utils/mask.util.spec.ts +21 -0
- package/templates/recipes/database-factories/README.md +48 -0
- package/templates/recipes/database-factories/tests/factories/base.factory.ts +51 -0
- package/templates/recipes/database-seeding/README.md +40 -0
- package/templates/recipes/database-seeding/src/infrastructure/database/seed.ts +61 -0
- package/templates/recipes/database-seeding/tests/unit/infrastructure/database/seed.spec.ts +37 -0
- package/templates/recipes/dead-letter-queue/README.md +79 -0
- package/templates/recipes/dead-letter-queue/src/infrastructure/queue/dlq.service.ts +43 -0
- package/templates/recipes/dead-letter-queue/tests/unit/infrastructure/queue/dlq.service.spec.ts +46 -0
- package/templates/recipes/dependabot-renovate/.github/dependabot.yml +52 -0
- package/templates/recipes/dependabot-renovate/README.md +37 -0
- package/templates/recipes/dependabot-renovate/renovate.json +46 -0
- package/templates/recipes/deploy/README.md +13 -0
- package/templates/recipes/deploy/docker-compose/README.md +38 -0
- package/templates/recipes/deploy/docker-compose/docker-compose.yml +43 -0
- package/templates/recipes/deploy/dockerfile/Dockerfile +30 -0
- package/templates/recipes/deploy/dockerfile/README.md +30 -0
- package/templates/recipes/deploy/dockerfile/dot-dockerignore +9 -0
- package/templates/recipes/deploy/kubernetes/README.md +43 -0
- package/templates/recipes/deploy/kubernetes/k8s/configmap.yaml +7 -0
- package/templates/recipes/deploy/kubernetes/k8s/deployment.yaml +45 -0
- package/templates/recipes/deploy/kubernetes/k8s/hpa.yaml +18 -0
- package/templates/recipes/deploy/kubernetes/k8s/ingress.yaml +23 -0
- package/templates/recipes/deploy/kubernetes/k8s/service.yaml +12 -0
- package/templates/recipes/deploy/serverless-framework/README.md +39 -0
- package/templates/recipes/deploy/serverless-framework/serverless.yml.ejs +22 -0
- package/templates/recipes/deploy/terraform/README.md +99 -0
- package/templates/recipes/deploy/terraform/main.tf.ejs +13 -0
- package/templates/recipes/deploy/terraform/modules/app/alb.tf +34 -0
- package/templates/recipes/deploy/terraform/modules/app/iam.tf +30 -0
- package/templates/recipes/deploy/terraform/modules/app/main.tf +80 -0
- package/templates/recipes/deploy/terraform/modules/app/outputs.tf +11 -0
- package/templates/recipes/deploy/terraform/modules/app/security.tf +37 -0
- package/templates/recipes/deploy/terraform/modules/app/variables.tf +42 -0
- package/templates/recipes/deploy/terraform/outputs.tf +4 -0
- package/templates/recipes/deploy/terraform/variables.tf +11 -0
- package/templates/recipes/devcontainer/.devcontainer/Dockerfile +5 -0
- package/templates/recipes/devcontainer/.devcontainer/devcontainer.json +32 -0
- package/templates/recipes/devcontainer/.devcontainer/docker-compose.yml +62 -0
- package/templates/recipes/devcontainer/README.md +31 -0
- package/templates/recipes/distributed-tracing/README.md +45 -0
- package/templates/recipes/distributed-tracing/src/shared/middleware/trace-propagation.middleware.ts +68 -0
- package/templates/recipes/distributed-tracing/tests/unit/shared/middleware/trace-propagation.middleware.spec.ts +76 -0
- package/templates/recipes/docker-compose-dev/Dockerfile.dev +14 -0
- package/templates/recipes/docker-compose-dev/README.md +57 -0
- package/templates/recipes/docker-compose-dev/docker-compose.dev.yml.ejs +54 -0
- package/templates/recipes/docs-site/README.md +41 -0
- package/templates/recipes/docs-site/docs/.vitepress/config.ts.ejs +53 -0
- package/templates/recipes/dpop/README.md +37 -0
- package/templates/recipes/dpop/src/shared/guards/dpop.guard.ts +61 -0
- package/templates/recipes/dpop/tests/unit/shared/guards/dpop.guard.spec.ts +69 -0
- package/templates/recipes/drizzle-postgres/README.md +68 -0
- package/templates/recipes/drizzle-postgres/drizzle.config.ts +10 -0
- package/templates/recipes/drizzle-postgres/src/infrastructure/database/drizzle.module.ts +25 -0
- package/templates/recipes/drizzle-postgres/src/infrastructure/database/schema/example.ts +9 -0
- package/templates/recipes/drizzle-postgres/src/infrastructure/database/schema/index.ts +3 -0
- package/templates/recipes/drizzle-postgres/tests/unit/infrastructure/database/drizzle.module.spec.ts +35 -0
- package/templates/recipes/env-per-environment/.env.development +17 -0
- package/templates/recipes/env-per-environment/.env.production +20 -0
- package/templates/recipes/env-per-environment/.env.test +17 -0
- package/templates/recipes/env-per-environment/README.md +40 -0
- package/templates/recipes/feature-flags/README.md +45 -0
- package/templates/recipes/feature-flags/src/shared/services/feature-flag.service.ts +48 -0
- package/templates/recipes/feature-flags/tests/unit/shared/services/feature-flag.service.spec.ts +36 -0
- package/templates/recipes/file-upload/README.md +104 -0
- package/templates/recipes/file-upload/src/shared/interceptors/file-upload.interceptor.ts +33 -0
- package/templates/recipes/file-upload/src/shared/pipes/file-validation.pipe.ts +45 -0
- package/templates/recipes/file-upload/tests/unit/shared/pipes/file-validation.pipe.spec.ts +56 -0
- package/templates/recipes/filtering/README.md +43 -0
- package/templates/recipes/filtering/src/shared/dto/filter.dto.ts +49 -0
- package/templates/recipes/filtering/tests/unit/shared/dto/filter.dto.spec.ts +38 -0
- package/templates/recipes/graceful-shutdown/README.md +60 -0
- package/templates/recipes/graceful-shutdown/src/shared/lifecycle/shutdown.service.ts +52 -0
- package/templates/recipes/graceful-shutdown/tests/unit/shared/lifecycle/shutdown.service.spec.ts +52 -0
- package/templates/recipes/graphql-mercurius/README.md +37 -0
- package/templates/recipes/graphql-mercurius/src/infrastructure/graphql/graphql.module.ts +18 -0
- package/templates/recipes/graphql-mercurius/tests/unit/infrastructure/graphql/graphql.module.spec.ts +12 -0
- package/templates/recipes/health-checks/README.md +35 -0
- package/templates/recipes/health-checks/src/shared/health/health.controller.ts +26 -0
- package/templates/recipes/health-checks/src/shared/health/health.module.ts +9 -0
- package/templates/recipes/health-checks/tests/unit/shared/health/health.controller.spec.ts +8 -0
- package/templates/recipes/helmet/README.md +43 -0
- package/templates/recipes/http-caching/README.md +63 -0
- package/templates/recipes/http-caching/src/shared/decorators/cache-control.decorator.ts +18 -0
- package/templates/recipes/http-caching/src/shared/interceptors/cache-control.interceptor.ts +43 -0
- package/templates/recipes/http-caching/tests/unit/shared/interceptors/cache-control.interceptor.spec.ts +44 -0
- package/templates/recipes/i18n/README.md +45 -0
- package/templates/recipes/i18n/src/i18n/en/common.json +7 -0
- package/templates/recipes/i18n/src/i18n/nl/common.json +7 -0
- package/templates/recipes/i18n/src/shared/i18n/i18n.module.ts +17 -0
- package/templates/recipes/i18n/tests/unit/shared/i18n/i18n.module.spec.ts +18 -0
- package/templates/recipes/idempotency/README.md +63 -0
- package/templates/recipes/idempotency/src/shared/decorators/idempotent.decorator.ts +4 -0
- package/templates/recipes/idempotency/src/shared/middleware/idempotency.middleware.ts +63 -0
- package/templates/recipes/idempotency/tests/unit/shared/middleware/idempotency.middleware.spec.ts +56 -0
- package/templates/recipes/json-merge-patch/README.md +53 -0
- package/templates/recipes/json-merge-patch/src/shared/pipes/merge-patch.pipe.ts +11 -0
- package/templates/recipes/json-merge-patch/tests/unit/shared/pipes/merge-patch.pipe.spec.ts +30 -0
- package/templates/recipes/json-patch/README.md +54 -0
- package/templates/recipes/json-patch/src/shared/pipes/json-patch.pipe.ts +39 -0
- package/templates/recipes/json-patch/tests/unit/shared/pipes/json-patch.pipe.spec.ts +37 -0
- package/templates/recipes/jwt-auth/README.md +56 -0
- package/templates/recipes/jwt-auth/src/shared/decorators/current-user.decorator.ts +10 -0
- package/templates/recipes/jwt-auth/src/shared/decorators/public.decorator.ts +4 -0
- package/templates/recipes/jwt-auth/src/shared/guards/jwt-auth.guard.ts +24 -0
- package/templates/recipes/jwt-auth/tests/unit/shared/guards/jwt-auth.guard.spec.ts +9 -0
- package/templates/recipes/kysely/README.md +53 -0
- package/templates/recipes/kysely/src/infrastructure/database/database.module.ts +28 -0
- package/templates/recipes/kysely/src/infrastructure/database/types.ts +17 -0
- package/templates/recipes/kysely/tests/unit/infrastructure/database/database.module.spec.ts +35 -0
- package/templates/recipes/license/LICENSE.agpl3 +59 -0
- package/templates/recipes/license/LICENSE.apache +189 -0
- package/templates/recipes/license/LICENSE.bsd3 +28 -0
- package/templates/recipes/license/LICENSE.gpl3 +22 -0
- package/templates/recipes/license/LICENSE.isc +15 -0
- package/templates/recipes/license/LICENSE.mit +21 -0
- package/templates/recipes/license/LICENSE.mpl2 +24 -0
- package/templates/recipes/license/LICENSE.proprietary +76 -0
- package/templates/recipes/license/LICENSE.unlicensed +13 -0
- package/templates/recipes/license/README.md +53 -0
- package/templates/recipes/load-testing/README.md +77 -0
- package/templates/recipes/load-testing/k6/smoke.js +20 -0
- package/templates/recipes/load-testing/k6/stress.js +22 -0
- package/templates/recipes/mfa-totp/README.md +77 -0
- package/templates/recipes/mfa-totp/src/shared/auth/totp.service.ts +26 -0
- package/templates/recipes/mfa-totp/tests/unit/shared/auth/totp.service.spec.ts +65 -0
- package/templates/recipes/mikro-orm/README.md +22 -0
- package/templates/recipes/mikro-orm/src/infrastructure/database/database.module.ts +8 -0
- package/templates/recipes/mikro-orm/src/infrastructure/database/entities/.gitkeep +0 -0
- package/templates/recipes/mikro-orm/src/infrastructure/database/migrations/.gitkeep +0 -0
- package/templates/recipes/mikro-orm/src/infrastructure/database/mikro-orm.config.ts +20 -0
- package/templates/recipes/mikro-orm/tests/unit/infrastructure/database/mikro-orm.config.spec.ts +53 -0
- package/templates/recipes/mongoose/README.md +42 -0
- package/templates/recipes/mongoose/src/infrastructure/database/database.module.ts.ejs +17 -0
- package/templates/recipes/mongoose/tests/unit/infrastructure/database/database.module.spec.ts +25 -0
- package/templates/recipes/multi-tenancy/README.md +49 -0
- package/templates/recipes/multi-tenancy/src/shared/decorators/tenant.decorator.ts +14 -0
- package/templates/recipes/multi-tenancy/src/shared/middleware/tenant.middleware.ts +49 -0
- package/templates/recipes/multi-tenancy/tests/unit/shared/middleware/tenant.middleware.spec.ts +29 -0
- package/templates/recipes/nodemailer/README.md +55 -0
- package/templates/recipes/nodemailer/src/infrastructure/notifications/mail.module.ts +37 -0
- package/templates/recipes/nodemailer/tests/unit/infrastructure/notifications/mail.module.spec.ts +33 -0
- package/templates/recipes/oauth-apple/README.md +68 -0
- package/templates/recipes/oauth-apple/src/shared/auth/apple-auth.guard.ts +5 -0
- package/templates/recipes/oauth-apple/src/shared/auth/apple.strategy.ts +33 -0
- package/templates/recipes/oauth-apple/tests/unit/shared/auth/apple.strategy.spec.ts +65 -0
- package/templates/recipes/oauth-github/README.md +62 -0
- package/templates/recipes/oauth-github/src/shared/auth/github-auth.guard.ts +5 -0
- package/templates/recipes/oauth-github/src/shared/auth/github.strategy.ts +33 -0
- package/templates/recipes/oauth-github/tests/unit/shared/auth/github.strategy.spec.ts +72 -0
- package/templates/recipes/oauth-google/README.md +64 -0
- package/templates/recipes/oauth-google/src/shared/auth/google-auth.guard.ts +5 -0
- package/templates/recipes/oauth-google/src/shared/auth/google.strategy.ts +33 -0
- package/templates/recipes/oauth-google/tests/unit/shared/auth/google.strategy.spec.ts +72 -0
- package/templates/recipes/oauth2-introspection/README.md +62 -0
- package/templates/recipes/oauth2-introspection/src/shared/guards/token-introspection.guard.ts +77 -0
- package/templates/recipes/oauth2-introspection/tests/unit/shared/guards/token-introspection.guard.spec.ts +99 -0
- package/templates/recipes/opentelemetry/README.md +44 -0
- package/templates/recipes/opentelemetry/src/infrastructure/telemetry/tracing.ts +38 -0
- package/templates/recipes/opentelemetry/tests/unit/infrastructure/telemetry/tracing.spec.ts +23 -0
- package/templates/recipes/pagination/README.md +71 -0
- package/templates/recipes/pagination/src/shared/decorators/paginate.decorator.ts +25 -0
- package/templates/recipes/pagination/src/shared/dto/pagination.dto.ts +64 -0
- package/templates/recipes/pagination/src/shared/interceptors/pagination-link.interceptor.ts +31 -0
- package/templates/recipes/pagination/tests/unit/shared/dto/pagination.dto.spec.ts +56 -0
- package/templates/recipes/passport/README.md +41 -0
- package/templates/recipes/passport/src/shared/guards/local-auth.guard.ts +5 -0
- package/templates/recipes/passport/tests/unit/shared/guards/local-auth.guard.spec.ts +17 -0
- package/templates/recipes/pino/README.md +48 -0
- package/templates/recipes/pino/src/infrastructure/logging/logger.module.ts +39 -0
- package/templates/recipes/pino/tests/unit/infrastructure/logging/logger.module.spec.ts +6 -0
- package/templates/recipes/prefer-header/README.md +92 -0
- package/templates/recipes/prefer-header/src/shared/interceptors/prefer.interceptor.ts +60 -0
- package/templates/recipes/prefer-header/tests/unit/shared/interceptors/prefer.interceptor.spec.ts +44 -0
- package/templates/recipes/prisma/README.md +52 -0
- package/templates/recipes/prisma/prisma/schema.prisma.ejs +8 -0
- package/templates/recipes/prisma/src/infrastructure/database/prisma.service.ts +27 -0
- package/templates/recipes/prisma/tests/unit/infrastructure/database/prisma.service.spec.ts +21 -0
- package/templates/recipes/prometheus/README.md +54 -0
- package/templates/recipes/prometheus/src/infrastructure/metrics/metrics.controller.ts +15 -0
- package/templates/recipes/prometheus/src/infrastructure/metrics/metrics.module.ts +29 -0
- package/templates/recipes/prometheus/tests/unit/infrastructure/metrics/metrics.controller.spec.ts +22 -0
- package/templates/recipes/rabbitmq/README.md +53 -0
- package/templates/recipes/rabbitmq/src/infrastructure/queue/queue.module.ts.ejs +27 -0
- package/templates/recipes/rbac-casl/README.md +69 -0
- package/templates/recipes/rbac-casl/src/shared/auth/casl-ability.factory.ts +43 -0
- package/templates/recipes/rbac-casl/src/shared/decorators/roles.decorator.ts +5 -0
- package/templates/recipes/rbac-casl/src/shared/guards/policies.guard.ts +32 -0
- package/templates/recipes/rbac-casl/src/shared/guards/roles.guard.ts +21 -0
- package/templates/recipes/rbac-casl/tests/unit/shared/auth/casl-ability.factory.spec.ts +6 -0
- package/templates/recipes/redis-cache/README.md +55 -0
- package/templates/recipes/redis-cache/src/infrastructure/cache/cache.module.ts +26 -0
- package/templates/recipes/redis-cache/tests/unit/infrastructure/cache/cache.module.spec.ts +12 -0
- package/templates/recipes/request-context/README.md +57 -0
- package/templates/recipes/request-context/src/shared/context/request-context.module.ts +19 -0
- package/templates/recipes/request-context/tests/unit/shared/context/request-context.module.spec.ts +20 -0
- package/templates/recipes/request-logging/README.md +36 -0
- package/templates/recipes/request-logging/src/shared/middleware/request-logging.middleware.ts +40 -0
- package/templates/recipes/request-logging/tests/unit/shared/middleware/request-logging.middleware.spec.ts +64 -0
- package/templates/recipes/s3-minio/README.md +52 -0
- package/templates/recipes/s3-minio/src/infrastructure/storage/storage.module.ts +10 -0
- package/templates/recipes/s3-minio/src/infrastructure/storage/storage.service.ts +72 -0
- package/templates/recipes/s3-minio/tests/unit/infrastructure/storage/storage.service.spec.ts +23 -0
- package/templates/recipes/sdk-generation/README.md +40 -0
- package/templates/recipes/sdk-generation/openapitools.json +21 -0
- package/templates/recipes/sendgrid/README.md +45 -0
- package/templates/recipes/sendgrid/src/infrastructure/notifications/sendgrid.service.ts +60 -0
- package/templates/recipes/sendgrid/tests/unit/infrastructure/notifications/sendgrid.service.spec.ts +59 -0
- package/templates/recipes/sentry/README.md +49 -0
- package/templates/recipes/sentry/src/infrastructure/sentry/sentry.filter.ts +34 -0
- package/templates/recipes/sentry/src/infrastructure/sentry/sentry.module.ts +23 -0
- package/templates/recipes/sentry/tests/unit/infrastructure/sentry/sentry.filter.spec.ts +50 -0
- package/templates/recipes/seq2/README.md +41 -0
- package/templates/recipes/seq2/src/infrastructure/logging/seq.transport.ts +57 -0
- package/templates/recipes/seq2/tests/unit/infrastructure/logging/seq.transport.spec.ts +53 -0
- package/templates/recipes/serialization-groups/README.md +105 -0
- package/templates/recipes/serialization-groups/src/shared/interceptors/serialize.interceptor.ts +29 -0
- package/templates/recipes/serialization-groups/tests/unit/shared/interceptors/serialize.interceptor.spec.ts +48 -0
- package/templates/recipes/soft-delete/README.md +71 -0
- package/templates/recipes/soft-delete/src/shared/decorators/with-deleted.decorator.ts +4 -0
- package/templates/recipes/soft-delete/src/shared/entities/soft-deletable.entity.ts +20 -0
- package/templates/recipes/soft-delete/tests/unit/shared/entities/soft-deletable.entity.spec.ts +35 -0
- package/templates/recipes/sse/README.md +43 -0
- package/templates/recipes/sse/src/shared/gateways/events.sse.controller.ts +21 -0
- package/templates/recipes/sse/tests/unit/shared/gateways/events.sse.controller.spec.ts +32 -0
- package/templates/recipes/swagger/README.md +42 -0
- package/templates/recipes/swagger/src/main.swagger.ts.ejs +20 -0
- package/templates/recipes/swagger/tests/unit/main.swagger.spec.ts +5 -0
- package/templates/recipes/throttler/README.md +49 -0
- package/templates/recipes/throttler/src/shared/guards/throttle.config.ts +33 -0
- package/templates/recipes/throttler/tests/unit/shared/guards/throttle.spec.ts +5 -0
- package/templates/recipes/transactional-outbox/README.md +98 -0
- package/templates/recipes/transactional-outbox/src/infrastructure/outbox/outbox.entity.ts +30 -0
- package/templates/recipes/transactional-outbox/src/infrastructure/outbox/outbox.service.ts +21 -0
- package/templates/recipes/transactional-outbox/tests/unit/infrastructure/outbox/outbox.service.spec.ts +38 -0
- package/templates/recipes/typeorm-mysql/README.md +48 -0
- package/templates/recipes/typeorm-mysql/src/infrastructure/database/database.module.ts.ejs +24 -0
- package/templates/recipes/typeorm-postgres/README.md +101 -0
- package/templates/recipes/typeorm-postgres/src/infrastructure/database/data-source.ts.ejs +14 -0
- package/templates/recipes/typeorm-postgres/src/infrastructure/database/database.module.ts.ejs +24 -0
- package/templates/recipes/typeorm-postgres/src/infrastructure/database/entities/.gitkeep +0 -0
- package/templates/recipes/typeorm-postgres/src/infrastructure/database/entities/index.ts +7 -0
- package/templates/recipes/typeorm-postgres/src/infrastructure/database/migrations/.gitkeep +0 -0
- package/templates/recipes/typeorm-postgres/src/infrastructure/database/migrations/index.ts +10 -0
- package/templates/recipes/typeorm-postgres/tests/unit/infrastructure/database/database.module.spec.ts +11 -0
- package/templates/recipes/webhooks/README.md +76 -0
- package/templates/recipes/webhooks/src/infrastructure/webhooks/webhook.service.ts +53 -0
- package/templates/recipes/webhooks/tests/unit/infrastructure/webhooks/webhook.service.spec.ts +31 -0
- package/templates/recipes/websockets/README.md +44 -0
- package/templates/recipes/websockets/src/shared/gateways/events.gateway.ts +55 -0
- package/templates/recipes/websockets/tests/unit/shared/gateways/events.gateway.spec.ts +23 -0
- package/templates/recipes/winston/README.md +45 -0
- package/templates/recipes/winston/src/infrastructure/logging/logger.module.ts +34 -0
- package/templates/recipes/winston/tests/unit/infrastructure/logging/logger.module.spec.ts +12 -0
- package/templates/recipes/worker-threads/README.md +71 -0
- package/templates/recipes/worker-threads/src/shared/utils/worker-pool.ts +59 -0
- package/templates/recipes/worker-threads/tests/unit/shared/utils/worker-pool.spec.ts +36 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# ADR-021: Observability Strategy with OpenTelemetry
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Date
|
|
8
|
+
|
|
9
|
+
2026-04-01
|
|
10
|
+
|
|
11
|
+
## Context
|
|
12
|
+
|
|
13
|
+
Production services require observability across three pillars: logs, traces, and metrics. Without a standardized approach, teams implement ad-hoc solutions that are inconsistent across services and difficult to correlate during incident response.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
Adopt OpenTelemetry (OTel) as the observability standard with the following components:
|
|
18
|
+
|
|
19
|
+
### Tracing
|
|
20
|
+
|
|
21
|
+
- `@opentelemetry/sdk-node` with auto-instrumentation for HTTP, database, and cache clients
|
|
22
|
+
- W3C Trace Context (`traceparent` header) for distributed trace propagation
|
|
23
|
+
- Trace IDs injected into Pino log lines via `nestjs-pino` for log-trace correlation
|
|
24
|
+
|
|
25
|
+
### Metrics
|
|
26
|
+
|
|
27
|
+
- `@opentelemetry/sdk-metrics` exporting to Prometheus via `/metrics` endpoint
|
|
28
|
+
- Default metrics: request duration histograms, error rate counters, active connection gauges
|
|
29
|
+
- Database connection pool metrics (pool size, idle, waiting) via custom instrumentation
|
|
30
|
+
- `@nestjs/terminus` health checks: liveness (`/health/live`), readiness (`/health/ready`), startup (`/health/startup`)
|
|
31
|
+
|
|
32
|
+
### Error Tracking
|
|
33
|
+
|
|
34
|
+
- Sentry (`@sentry/nestjs`) for error aggregation, release tracking, and performance monitoring
|
|
35
|
+
- Available as the `sentry` recipe — not baked into the base template
|
|
36
|
+
- Source maps uploaded to Sentry during CI/CD build stage
|
|
37
|
+
|
|
38
|
+
### Request Logging
|
|
39
|
+
|
|
40
|
+
- Request/response logging middleware via `nestjs-pino` with correlation ID propagation
|
|
41
|
+
- Configurable log sampling for high-traffic endpoints
|
|
42
|
+
|
|
43
|
+
## Consequences
|
|
44
|
+
|
|
45
|
+
### Positive
|
|
46
|
+
|
|
47
|
+
- OpenTelemetry is vendor-neutral — exporters can target Jaeger, Datadog, New Relic, or cloud-native backends
|
|
48
|
+
- W3C Trace Context ensures trace propagation works across any OTel-instrumented service
|
|
49
|
+
- Health check probes integrate with Kubernetes liveness/readiness/startup probe configuration
|
|
50
|
+
- Connection pool monitoring catches resource exhaustion before it causes outages
|
|
51
|
+
|
|
52
|
+
### Negative
|
|
53
|
+
|
|
54
|
+
- OpenTelemetry SDK adds startup overhead and memory for span collection
|
|
55
|
+
- Auto-instrumentation can generate high trace volume — requires sampling configuration
|
|
56
|
+
- Prometheus `/metrics` endpoint must be secured in production (not exposed publicly)
|
|
57
|
+
|
|
58
|
+
### Risks
|
|
59
|
+
|
|
60
|
+
- OpenTelemetry Node.js SDK maturity — some instrumentations are still in beta; mitigated by pinning to stable releases
|
|
61
|
+
|
|
62
|
+
## References
|
|
63
|
+
|
|
64
|
+
- [OpenTelemetry JS](https://opentelemetry.io/docs/languages/js/)
|
|
65
|
+
- [W3C Trace Context](https://www.w3.org/TR/trace-context/)
|
|
66
|
+
- Packages: `@opentelemetry/sdk-node`, `@opentelemetry/sdk-metrics`, `@nestjs/terminus`, `@sentry/nestjs`
|
|
67
|
+
- Recipes: `sentry`, `datadog`, `prometheus`
|
|
68
|
+
- ADR-017: Logging Strategy
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# ADR-022: API Design Patterns as Opt-In Recipes
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Date
|
|
8
|
+
|
|
9
|
+
2026-04-01
|
|
10
|
+
|
|
11
|
+
## Context
|
|
12
|
+
|
|
13
|
+
Production APIs need patterns like pagination, filtering, caching, and idempotency. However, not every API needs every pattern. Baking all patterns into the base template would add complexity and dependencies that many projects never use.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
Provide API design patterns as individual opt-in recipes, each implementing a well-defined RFC or industry standard:
|
|
18
|
+
|
|
19
|
+
| Recipe | Standard | Description |
|
|
20
|
+
| ---------------- | ----------------------- | ------------------------------------------------------------------------------ |
|
|
21
|
+
| `pagination` | RFC 8288 (Web Linking) | Cursor and offset pagination with `Link` header navigation |
|
|
22
|
+
| `filtering` | Custom (JSON query DSL) | Type-safe query filtering with `class-validator` DTOs |
|
|
23
|
+
| `api-versioning` | URI + Header | URI prefix (`/v1/`) and `Accept-Version` header strategies |
|
|
24
|
+
| `correlation-id` | Custom | `x-correlation-id` header propagation via `AsyncLocalStorage` |
|
|
25
|
+
| `idempotency` | Idempotency-Key header | Request deduplication with configurable storage (Redis/database) |
|
|
26
|
+
| `http-caching` | RFC 9111 | `Cache-Control`, `ETag`, and conditional request support |
|
|
27
|
+
| `prefer-header` | RFC 7240 | `Prefer: return=minimal`, `respond-async` handling |
|
|
28
|
+
| `json-patch` | RFC 6902 | JSON Patch operations for partial resource updates |
|
|
29
|
+
| `sse` | EventSource API | Server-Sent Events for real-time unidirectional streaming |
|
|
30
|
+
| `webhooks` | Custom | Webhook dispatch with retry, signing (`content-digest`), and delivery tracking |
|
|
31
|
+
|
|
32
|
+
Each recipe provides:
|
|
33
|
+
|
|
34
|
+
- A NestJS module or decorator that can be imported per-controller
|
|
35
|
+
- DTOs with `class-validator` decorators for input validation
|
|
36
|
+
- Integration tests demonstrating correct behavior
|
|
37
|
+
- CLAUDE.md documentation for AI-assisted development
|
|
38
|
+
|
|
39
|
+
## Consequences
|
|
40
|
+
|
|
41
|
+
### Positive
|
|
42
|
+
|
|
43
|
+
- APIs adopt only the patterns they need — no unused middleware or decorators
|
|
44
|
+
- Each pattern follows an established RFC, ensuring interoperability
|
|
45
|
+
- Recipes include tests and documentation, reducing implementation errors
|
|
46
|
+
- Patterns are composable — `pagination` + `filtering` + `http-caching` work together
|
|
47
|
+
|
|
48
|
+
### Negative
|
|
49
|
+
|
|
50
|
+
- Developers must know which recipes to select — requires familiarity with API design patterns
|
|
51
|
+
- Some recipes depend on others (e.g., `webhooks` benefits from `correlation-id`)
|
|
52
|
+
- Recipe-per-pattern granularity means more items in the CLI selection prompt
|
|
53
|
+
|
|
54
|
+
### Risks
|
|
55
|
+
|
|
56
|
+
- RFC compliance drift as recipes evolve — mitigated by linking to the relevant RFC in each recipe's README and validating compliance in integration tests
|
|
57
|
+
|
|
58
|
+
## References
|
|
59
|
+
|
|
60
|
+
- [RFC 8288 — Web Linking](https://www.rfc-editor.org/rfc/rfc8288)
|
|
61
|
+
- [RFC 9111 — HTTP Caching](https://www.rfc-editor.org/rfc/rfc9111)
|
|
62
|
+
- [RFC 7240 — Prefer Header](https://www.rfc-editor.org/rfc/rfc7240)
|
|
63
|
+
- [RFC 6902 — JSON Patch](https://www.rfc-editor.org/rfc/rfc6902)
|
|
64
|
+
- ADR-008: Composable Recipe System
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# ADR-023: Typed Error Class Hierarchy
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Date
|
|
8
|
+
|
|
9
|
+
2026-05-01
|
|
10
|
+
|
|
11
|
+
## Context
|
|
12
|
+
|
|
13
|
+
NestJS provides `HttpException` and its subclasses (`NotFoundException`, `BadRequestException`, etc.) for throwing HTTP errors. However, these are HTTP-layer concerns — using them in domain services couples business logic to the HTTP transport. Services that throw `HttpException` cannot be reused in message consumers, CLI commands, or gRPC handlers without dragging in HTTP semantics.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
Implement a typed error hierarchy rooted at `ApplicationError`:
|
|
18
|
+
|
|
19
|
+
- **`ApplicationError`** — abstract base with `message`, `traceCode`, and optional `debugInformation`
|
|
20
|
+
- **`ValidationError`** — input validation failures (maps to 400)
|
|
21
|
+
- **`NotFoundError`** — requested resource does not exist (maps to 404)
|
|
22
|
+
- **`ForbiddenError`** — authenticated user lacks permission (maps to 403)
|
|
23
|
+
- **`InvalidRequestError`** — structurally valid but semantically invalid request (maps to 422)
|
|
24
|
+
- **`RequesterError`** — upstream/third-party service returned an error (maps to 502)
|
|
25
|
+
|
|
26
|
+
Key design choices:
|
|
27
|
+
|
|
28
|
+
- **Static trace codes:** each error instance carries a `traceCode` (e.g., `USR_001`) that is grep-searchable across the codebase, enabling instant error origin identification in logs and monitoring
|
|
29
|
+
- **`debugInformation` separation:** debug context (stack traces, internal state) is attached to the error but excluded from production API responses via the exception filter, preventing information leakage
|
|
30
|
+
- **Transport-agnostic mapping:** the global exception filter maps `ApplicationError` subclasses to HTTP status codes; a separate gRPC or message handler filter can map the same errors to its own status codes
|
|
31
|
+
|
|
32
|
+
## Consequences
|
|
33
|
+
|
|
34
|
+
### Positive
|
|
35
|
+
|
|
36
|
+
- Domain services remain transport-agnostic and reusable across HTTP, gRPC, and message consumers
|
|
37
|
+
- Trace codes enable instant error location via `grep -r "USR_001"` across the entire codebase
|
|
38
|
+
- Debug information is available in development and logging but never leaked to API consumers in production
|
|
39
|
+
- Type-safe error handling — callers can catch specific error types rather than checking status codes
|
|
40
|
+
|
|
41
|
+
### Negative
|
|
42
|
+
|
|
43
|
+
- Additional class hierarchy to maintain alongside NestJS built-in exceptions
|
|
44
|
+
- Developers must remember to throw `ApplicationError` subclasses instead of `HttpException`
|
|
45
|
+
- Exception filter mapping logic must be kept in sync with new error types
|
|
46
|
+
|
|
47
|
+
### Risks
|
|
48
|
+
|
|
49
|
+
- Inconsistent adoption — mitigated by ESLint rule banning direct `HttpException` usage in service files
|
|
50
|
+
|
|
51
|
+
## References
|
|
52
|
+
|
|
53
|
+
- ADR-002: RFC 9457 Problem Details for Error Responses
|
|
54
|
+
- Package: `@nestjs/common` (exception filters)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# ADR-024: Request Context via AsyncLocalStorage (CLS)
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Date
|
|
8
|
+
|
|
9
|
+
2026-05-01
|
|
10
|
+
|
|
11
|
+
## Context
|
|
12
|
+
|
|
13
|
+
Cross-cutting request data (correlation ID, authenticated user, tenant ID) must be available throughout the call chain — in services, repositories, interceptors, and event handlers. Two approaches exist in NestJS: REQUEST-scoped injection and continuation-local storage (CLS) via `AsyncLocalStorage`.
|
|
14
|
+
|
|
15
|
+
REQUEST-scoped providers force NestJS to create new instances of every dependent provider per request. This causes significant memory pressure and GC overhead under load, as the entire dependency subtree becomes request-scoped (the "scope bubble" problem).
|
|
16
|
+
|
|
17
|
+
## Decision
|
|
18
|
+
|
|
19
|
+
Use `nestjs-cls` (backed by Node.js `AsyncLocalStorage`) to propagate request context. Key design choices:
|
|
20
|
+
|
|
21
|
+
- **CLS store initialization:** a `ClsMiddleware` runs first in the middleware chain, creating the store and generating a correlation ID (from `x-correlation-id` header or UUID)
|
|
22
|
+
- **User and tenant enrichment:** a `ClsGuard` or interceptor populates `cls.set('user', ...)` and `cls.set('tenantId', ...)` after authentication
|
|
23
|
+
- **Access pattern:** services inject `ClsService` and call `cls.get('correlationId')` — no constructor parameters, no method parameter drilling
|
|
24
|
+
- **All providers remain DEFAULT scope:** no provider needs REQUEST scope, preserving singleton performance characteristics
|
|
25
|
+
|
|
26
|
+
## Consequences
|
|
27
|
+
|
|
28
|
+
### Positive
|
|
29
|
+
|
|
30
|
+
- Zero memory overhead per request — all providers remain singleton-scoped
|
|
31
|
+
- Correlation ID, user, and tenant are available anywhere in the call chain without parameter passing
|
|
32
|
+
- Works across async boundaries including `Promise.all`, `setTimeout`, and event emitters
|
|
33
|
+
- Compatible with Pino's request-scoped logging (ADR-017) — same correlation ID in both systems
|
|
34
|
+
|
|
35
|
+
### Negative
|
|
36
|
+
|
|
37
|
+
- `AsyncLocalStorage` is an implicit dependency — harder to trace data flow than explicit parameters
|
|
38
|
+
- CLS context is lost across worker threads and child processes unless explicitly propagated
|
|
39
|
+
- Developers unfamiliar with CLS may find the "magic" context confusing
|
|
40
|
+
|
|
41
|
+
### Risks
|
|
42
|
+
|
|
43
|
+
- CLS context loss in edge cases (native addons, some ORMs with custom connection pools) — mitigated by integration tests verifying context propagation
|
|
44
|
+
|
|
45
|
+
## Alternatives Considered
|
|
46
|
+
|
|
47
|
+
### REQUEST-scoped providers
|
|
48
|
+
|
|
49
|
+
- **Pros:** native NestJS pattern, explicit dependency injection
|
|
50
|
+
- **Cons:** every dependent provider becomes request-scoped, creating new instances per request; 30-50% throughput reduction in benchmarks
|
|
51
|
+
- **Why not:** performance cost is unacceptable for high-throughput services
|
|
52
|
+
|
|
53
|
+
## References
|
|
54
|
+
|
|
55
|
+
- Package: `nestjs-cls`
|
|
56
|
+
- Node.js API: `AsyncLocalStorage`
|
|
57
|
+
- ADR-017: Structured JSON Logging with Pino
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# ADR-025: Opt-in Data Patterns (Soft Delete, Audit Trail, Outbox)
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Date
|
|
8
|
+
|
|
9
|
+
2026-05-01
|
|
10
|
+
|
|
11
|
+
## Context
|
|
12
|
+
|
|
13
|
+
Production applications frequently need soft delete (logical deletion without data loss), audit trails (who changed what and when), and guaranteed event delivery (outbox pattern). These are cross-cutting concerns that not every service or entity needs — mandating them globally would add unnecessary complexity and storage overhead to simple CRUD entities.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
Provide each data pattern as a separate opt-in recipe that can be applied per entity or globally:
|
|
18
|
+
|
|
19
|
+
### Soft Delete
|
|
20
|
+
|
|
21
|
+
- TypeORM `@DeleteDateColumn()` on entities needing logical deletion; `softDelete(id)` / `restore(id)`
|
|
22
|
+
- Global query filter excludes soft-deleted rows by default; `withDeleted()` to include them
|
|
23
|
+
|
|
24
|
+
### Audit Trail
|
|
25
|
+
|
|
26
|
+
- `AuditInterceptor` captures entity snapshots before and after mutations, storing diffs in `audit_log`
|
|
27
|
+
- User context sourced from CLS (ADR-024); configurable per entity via `@Auditable()` decorator
|
|
28
|
+
|
|
29
|
+
### Transactional Outbox
|
|
30
|
+
|
|
31
|
+
- Events written to an `outbox` table in the same database transaction as the business write
|
|
32
|
+
- A poller or CDC process reads the outbox and publishes to the broker, preventing dual-write inconsistency
|
|
33
|
+
|
|
34
|
+
## Consequences
|
|
35
|
+
|
|
36
|
+
### Positive
|
|
37
|
+
|
|
38
|
+
- Each pattern is independently adoptable — no all-or-nothing commitment
|
|
39
|
+
- Soft delete preserves data for compliance and recovery without backup restores
|
|
40
|
+
- Audit trail provides a complete change history for regulatory and debugging purposes
|
|
41
|
+
- Outbox pattern eliminates the distributed transaction problem for event-driven architectures
|
|
42
|
+
|
|
43
|
+
### Negative
|
|
44
|
+
|
|
45
|
+
- Soft delete increases table sizes and requires `withDeleted()` awareness in queries
|
|
46
|
+
- Audit trail adds write amplification — every mutation produces an additional insert
|
|
47
|
+
- Outbox poller introduces publication latency (configurable polling interval)
|
|
48
|
+
|
|
49
|
+
### Risks
|
|
50
|
+
|
|
51
|
+
- Soft-deleted data accumulating indefinitely — mitigated by scheduled cleanup jobs for records past retention period
|
|
52
|
+
- Outbox table growing under high write throughput — mitigated by immediate deletion after successful publish
|
|
53
|
+
|
|
54
|
+
## References
|
|
55
|
+
|
|
56
|
+
- ADR-003: Database Strategy
|
|
57
|
+
- ADR-024: Request Context via AsyncLocalStorage (CLS)
|
|
58
|
+
- Pattern reference: microservices.io/patterns/data/transactional-outbox
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# ADR-026: Database Migration Strategy (Lambda Runner Pattern)
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Date
|
|
8
|
+
|
|
9
|
+
2026-05-01
|
|
10
|
+
|
|
11
|
+
## Context
|
|
12
|
+
|
|
13
|
+
Database migrations in serverless deployments cannot run via traditional CLI commands (`typeorm migration:run`) because there is no persistent server process. Migrations must execute before the application starts serving traffic, with validation that they succeeded. Running migrations at application startup is risky — multiple concurrent Lambda instances could race on the same migration.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
Use a dedicated migration-runner Lambda function that executes database migrations as a discrete pipeline step. Key design choices:
|
|
18
|
+
|
|
19
|
+
- **Pipeline integration:** deploy migration-runner Lambda, invoke it, validate exit code, then deploy the application Lambda. If migration fails, the pipeline halts before the new application code is deployed
|
|
20
|
+
- **ORM-agnostic architecture:** the migration runner is a thin wrapper that calls the ORM's migration API programmatically (`dataSource.runMigrations()` for TypeORM) rather than shelling out to CLI commands
|
|
21
|
+
- **Barrel file pattern:** TypeORM with esbuild/Lambda requires explicit migration imports via a barrel file (`migrations/index.ts` re-exporting all migration classes) because esbuild cannot resolve TypeORM's glob-based migration discovery
|
|
22
|
+
- **Local dev CLI:** developers use the standard `typeorm migration:run` CLI locally; the Lambda handler and CLI entrypoint share the same `DataSource` configuration but have separate entrypoints
|
|
23
|
+
- **Idempotency:** TypeORM's migration table (`migrations`) tracks executed migrations; re-invoking the runner is safe
|
|
24
|
+
|
|
25
|
+
## Consequences
|
|
26
|
+
|
|
27
|
+
### Positive
|
|
28
|
+
|
|
29
|
+
- Migrations run exactly once before application deployment — no race conditions from concurrent instances
|
|
30
|
+
- Pipeline can gate deployment on migration success, preventing schema-code mismatches
|
|
31
|
+
- Same migration code runs locally (CLI) and in production (Lambda) — no environment-specific migration logic
|
|
32
|
+
- Barrel file pattern works reliably with esbuild tree-shaking and bundling
|
|
33
|
+
|
|
34
|
+
### Negative
|
|
35
|
+
|
|
36
|
+
- Additional Lambda function to deploy and maintain
|
|
37
|
+
- Barrel file must be manually updated when adding new migrations (or automated via codegen script)
|
|
38
|
+
- Pipeline is slightly slower due to the additional deploy-invoke-validate step
|
|
39
|
+
|
|
40
|
+
### Risks
|
|
41
|
+
|
|
42
|
+
- Migration timeout on large tables — mitigated by setting Lambda timeout to 15 minutes and using batched DDL operations
|
|
43
|
+
- Barrel file drift (missing migration) — mitigated by a CI check that verifies all migration files are re-exported
|
|
44
|
+
|
|
45
|
+
## Alternatives Considered
|
|
46
|
+
|
|
47
|
+
### Run migrations at application startup
|
|
48
|
+
|
|
49
|
+
- **Pros:** simpler deployment, no extra Lambda
|
|
50
|
+
- **Cons:** race conditions with multiple instances, startup latency, failed migration leaves app in broken state
|
|
51
|
+
- **Why not:** unsafe in multi-instance serverless environments
|
|
52
|
+
|
|
53
|
+
## References
|
|
54
|
+
|
|
55
|
+
- ADR-003: Database Strategy
|
|
56
|
+
- ADR-005: Deployment Strategy
|
|
57
|
+
- ADR-014: Build Toolchain
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# ADR-027: Dependency Management with pnpm
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Date
|
|
8
|
+
|
|
9
|
+
2026-05-01
|
|
10
|
+
|
|
11
|
+
## Context
|
|
12
|
+
|
|
13
|
+
Node.js package managers (npm, yarn, pnpm) differ significantly in installation speed, disk usage, dependency resolution strictness, and monorepo support. The boilerplate needs a package manager that supports the monorepo workspace layout (ADR-012), enforces strict dependency boundaries, and prevents phantom dependencies.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
Use **pnpm** as the sole package manager for all projects scaffolded by the boilerplate. Key design choices:
|
|
18
|
+
|
|
19
|
+
- **Strict mode:** pnpm's default content-addressable store and symlink-based `node_modules` prevent phantom dependencies (packages that work by accident because a transitive dependency hoisted them)
|
|
20
|
+
- **Exact versions:** `.npmrc` includes `save-exact=true` so `pnpm add` writes exact versions (e.g., `4.18.2` not `^4.18.2`), preventing unexpected minor/patch updates
|
|
21
|
+
- **Workspace support:** `pnpm-workspace.yaml` defines the monorepo package topology; `workspace:*` protocol for internal package references
|
|
22
|
+
- **Lockfile integrity:** `pnpm-lock.yaml` is committed and CI runs `pnpm install --frozen-lockfile` to ensure reproducible installs
|
|
23
|
+
- **Automated updates:** Renovate or Dependabot configuration is provided as a recipe, configured to open PRs with exact version bumps on a weekly schedule
|
|
24
|
+
- **Security auditing:** pre-push hook runs `pnpm audit --audit-level=high` to catch known vulnerabilities before code reaches the remote
|
|
25
|
+
|
|
26
|
+
## Consequences
|
|
27
|
+
|
|
28
|
+
### Positive
|
|
29
|
+
|
|
30
|
+
- Content-addressable store saves disk space via shared package cache across projects
|
|
31
|
+
- Strict `node_modules` layout catches missing `dependencies` declarations that npm/yarn silently resolve
|
|
32
|
+
- Exact versions eliminate drift between development, CI, and production environments
|
|
33
|
+
|
|
34
|
+
### Negative
|
|
35
|
+
|
|
36
|
+
- Some packages with native bindings may need `pnpm.overrides` or `pnpm.patchedDependencies`
|
|
37
|
+
- Developers accustomed to npm/yarn need to adopt pnpm-specific commands
|
|
38
|
+
|
|
39
|
+
### Risks
|
|
40
|
+
|
|
41
|
+
- pnpm adoption is lower than npm — mitigated by pnpm's growing ecosystem support and corepack integration in Node.js
|
|
42
|
+
|
|
43
|
+
## Alternatives Considered
|
|
44
|
+
|
|
45
|
+
### npm
|
|
46
|
+
|
|
47
|
+
- **Pros:** default with Node.js, universal familiarity
|
|
48
|
+
- **Cons:** flat `node_modules` allows phantom dependencies, slower installs, weaker workspace support
|
|
49
|
+
- **Why not:** phantom dependencies cause production failures that are difficult to diagnose
|
|
50
|
+
|
|
51
|
+
### yarn (v3+)
|
|
52
|
+
|
|
53
|
+
- **Pros:** Plug'n'Play for zero-install, good workspace support
|
|
54
|
+
- **Cons:** PnP mode has compatibility issues with many packages, complex configuration
|
|
55
|
+
- **Why not:** pnpm achieves similar benefits with better compatibility
|
|
56
|
+
|
|
57
|
+
## References
|
|
58
|
+
|
|
59
|
+
- ADR-012: Monorepo Strategy
|
|
60
|
+
- Configuration: `.npmrc`, `pnpm-workspace.yaml`
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# ADR-028: Code Quality Toolchain (ESLint, Prettier, Commitlint, Husky)
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Date
|
|
8
|
+
|
|
9
|
+
2026-05-01
|
|
10
|
+
|
|
11
|
+
## Context
|
|
12
|
+
|
|
13
|
+
Code quality enforcement via manual review is inconsistent and slow. Automated tooling must catch formatting, lint, commit message, and type errors before code reaches the remote. The toolchain must be fast enough that developers do not bypass it.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
Use a layered git hook pipeline with ESLint flat config, Prettier, commitlint, lint-staged, and husky:
|
|
18
|
+
|
|
19
|
+
### Pre-commit (lint-staged)
|
|
20
|
+
|
|
21
|
+
- **ESLint** on staged `.ts` files (flat config) + **Prettier** on staged files (TS, JSON, YAML, MD)
|
|
22
|
+
- lint-staged processes only staged files, keeping the hook under 5 seconds
|
|
23
|
+
|
|
24
|
+
### Commit-msg (commitlint)
|
|
25
|
+
|
|
26
|
+
- Enforces Conventional Commits: `<type>(<scope>): <description>`, kebab-case scope, lowercase description
|
|
27
|
+
|
|
28
|
+
### Pre-push
|
|
29
|
+
|
|
30
|
+
- `tsc --noEmit` + `pnpm test` — type-check and unit tests must pass
|
|
31
|
+
- Branch name validation enforces naming convention (`feature/`, `fix/`, `chore/`, etc.)
|
|
32
|
+
|
|
33
|
+
## Consequences
|
|
34
|
+
|
|
35
|
+
### Positive
|
|
36
|
+
|
|
37
|
+
- Zero formatting debates — Prettier is the single source of truth
|
|
38
|
+
- Consistent commit history enables automated changelog generation and semantic versioning
|
|
39
|
+
- Type errors and test failures caught before push prevent broken CI builds
|
|
40
|
+
|
|
41
|
+
### Negative
|
|
42
|
+
|
|
43
|
+
- Five tools to configure; pre-push hook adds 10-30 seconds that developers may perceive as friction
|
|
44
|
+
|
|
45
|
+
### Risks
|
|
46
|
+
|
|
47
|
+
- Developers bypassing hooks with `--no-verify` — mitigated by CI running the same checks, so bypassed commits fail in pipeline
|
|
48
|
+
|
|
49
|
+
## Alternatives Considered
|
|
50
|
+
|
|
51
|
+
### Biome (formerly Rome)
|
|
52
|
+
|
|
53
|
+
- **Pros:** single tool for linting and formatting, faster than ESLint + Prettier
|
|
54
|
+
- **Cons:** smaller plugin ecosystem, no commitlint equivalent
|
|
55
|
+
- **Why not:** ESLint's plugin ecosystem (TypeORM, NestJS-specific rules) is essential
|
|
56
|
+
|
|
57
|
+
## References
|
|
58
|
+
|
|
59
|
+
- ADR-009: Standards Compliance
|
|
60
|
+
- Packages: `eslint`, `prettier`, `@commitlint/cli`, `lint-staged`, `husky`
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# ADR-029: AdminJS as Admin Panel Recipe
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Date
|
|
8
|
+
|
|
9
|
+
2026-05-01
|
|
10
|
+
|
|
11
|
+
## Context
|
|
12
|
+
|
|
13
|
+
Most backend applications eventually need an admin panel for data inspection, manual corrections, and operational tasks. Building a custom admin UI is expensive and rarely differentiated — the effort is better spent on the core product. The admin panel must integrate with the existing ORM and authentication without requiring a separate frontend deployment.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
Provide AdminJS as an opt-in recipe for auto-generated admin panels. Key design choices:
|
|
18
|
+
|
|
19
|
+
- **Auto-generated CRUD:** AdminJS introspects ORM entity metadata to generate list, show, create, edit, and delete views with filtering, sorting, and pagination — no manual form definitions required
|
|
20
|
+
- **ORM adapter pattern:** the recipe uses `@adminjs/typeorm` by default; adapters exist for Prisma (`@adminjs/prisma`), Mongoose (`@adminjs/mongoose`), and MikroORM (`@adminjs/mikroorm`), matching the boilerplate's ORM-agnostic philosophy
|
|
21
|
+
- **NestJS integration:** `@adminjs/nestjs` mounts AdminJS as a NestJS module at `/admin`, sharing the application's dependency injection container and middleware pipeline
|
|
22
|
+
- **Authentication:** environment-based credentials (`ADMIN_EMAIL`, `ADMIN_PASSWORD`) for simplicity in development and staging; production deployments should integrate with the application's auth system (ADR-004)
|
|
23
|
+
- **Customization escape hatches:** custom actions, components, and dashboard widgets can be added per-resource without ejecting from the framework
|
|
24
|
+
|
|
25
|
+
### When to use AdminJS vs custom admin
|
|
26
|
+
|
|
27
|
+
- **Use AdminJS:** internal data browsing, support team tools, content management, entity CRUD operations
|
|
28
|
+
- **Build custom:** customer-facing dashboards, complex multi-step workflows, real-time data visualization, highly branded experiences
|
|
29
|
+
|
|
30
|
+
## Consequences
|
|
31
|
+
|
|
32
|
+
### Positive
|
|
33
|
+
|
|
34
|
+
- Admin panel available in minutes rather than weeks of custom development
|
|
35
|
+
- Entity schema changes automatically reflected in the admin UI — no form maintenance
|
|
36
|
+
- Single deployment — admin panel runs within the NestJS application process
|
|
37
|
+
- ORM adapter swap requires only changing the adapter package, not rewriting admin configuration
|
|
38
|
+
|
|
39
|
+
### Negative
|
|
40
|
+
|
|
41
|
+
- AdminJS bundles a React frontend that increases the application's dependency footprint
|
|
42
|
+
- Customization beyond standard CRUD requires learning AdminJS's component API
|
|
43
|
+
- Performance may degrade with very large datasets without explicit pagination configuration
|
|
44
|
+
|
|
45
|
+
### Risks
|
|
46
|
+
|
|
47
|
+
- Security exposure if admin routes are not properly protected — mitigated by authentication guard and network-level access controls (VPN, IP allowlist)
|
|
48
|
+
|
|
49
|
+
## References
|
|
50
|
+
|
|
51
|
+
- ADR-003: Database Strategy
|
|
52
|
+
- ADR-004: Authentication Architecture
|
|
53
|
+
- Packages: `adminjs`, `@adminjs/nestjs`, `@adminjs/typeorm`
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# ADR-030: Performance Patterns (Workers, Circuit Breaker, Caching, Load Testing)
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Date
|
|
8
|
+
|
|
9
|
+
2026-05-01
|
|
10
|
+
|
|
11
|
+
## Context
|
|
12
|
+
|
|
13
|
+
Node.js is single-threaded — CPU-intensive operations block the event loop and degrade throughput. External service calls can cascade failures when a dependency is unavailable. Without load testing, performance regressions reach production undetected.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
Provide a set of performance recipes that address common bottlenecks:
|
|
18
|
+
|
|
19
|
+
### Worker Threads for CPU-intensive tasks
|
|
20
|
+
|
|
21
|
+
- Use `worker_threads` for operations exceeding 50ms CPU time (PDF generation, image processing, CSV parsing)
|
|
22
|
+
- `WorkerPool` manages reusable workers; communication via `MessagePort` with serializable data only
|
|
23
|
+
|
|
24
|
+
### Circuit Breaker (opossum)
|
|
25
|
+
|
|
26
|
+
- Wrap external calls with `opossum`; open after 5 failures in 30s, half-open retry after 10s
|
|
27
|
+
- Fallback functions provide degraded responses when circuit is open; state changes emit monitoring events
|
|
28
|
+
|
|
29
|
+
### Connection Pool Sizing and ETags
|
|
30
|
+
|
|
31
|
+
- Database pool: `(CPU cores * 2) + 1` baseline; HTTP clients: `keepAlive: true` with bounded `maxSockets`
|
|
32
|
+
- `EtagInterceptor` returns `304 Not Modified` for unchanged responses, reducing bandwidth
|
|
33
|
+
|
|
34
|
+
### Request Timeout and Load Testing
|
|
35
|
+
|
|
36
|
+
- Global timeout middleware (default 30s) returns `408` with Problem Details response (ADR-002)
|
|
37
|
+
- k6 scripts in `test/load/` for smoke, load, stress, and soak scenarios; smoke tests run per PR in CI
|
|
38
|
+
|
|
39
|
+
## Consequences
|
|
40
|
+
|
|
41
|
+
### Positive
|
|
42
|
+
|
|
43
|
+
- Worker threads keep the event loop responsive during CPU-intensive operations
|
|
44
|
+
- Circuit breakers prevent cascade failures; ETags reduce bandwidth costs
|
|
45
|
+
- k6 integration catches performance regressions before production deployment
|
|
46
|
+
|
|
47
|
+
### Negative
|
|
48
|
+
|
|
49
|
+
- Worker pool adds memory overhead (each worker is a separate V8 isolate)
|
|
50
|
+
- Circuit breaker thresholds require per-dependency tuning
|
|
51
|
+
|
|
52
|
+
### Risks
|
|
53
|
+
|
|
54
|
+
- Misconfigured circuit breaker thresholds — mitigated by monitoring alerts on circuit state changes
|
|
55
|
+
|
|
56
|
+
## References
|
|
57
|
+
|
|
58
|
+
- ADR-002: RFC 9457 Problem Details for Error Responses
|
|
59
|
+
- ADR-017: Structured JSON Logging with Pino
|
|
60
|
+
- Packages: `opossum`, `k6`; Node.js API: `worker_threads`
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# ADR-031: Nx Generators for Post-Scaffolding Recipe Management
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Proposed
|
|
6
|
+
|
|
7
|
+
## Date
|
|
8
|
+
|
|
9
|
+
2026-05-12
|
|
10
|
+
|
|
11
|
+
## Context
|
|
12
|
+
|
|
13
|
+
The current `spoonfeeder` CLI generates projects with selected recipes at creation time. However, teams frequently need to add recipes after project creation (e.g., adding Swagger to an existing API, adding Redis caching mid-project). Currently this requires manual integration.
|
|
14
|
+
|
|
15
|
+
Nx Generators can modify existing TypeScript files safely using AST transforms, making it possible to:
|
|
16
|
+
|
|
17
|
+
- Add a recipe to an existing project (`nx g spoonfeeder:add-recipe swagger`)
|
|
18
|
+
- Remove a recipe (`nx g spoonfeeder:remove-recipe pino`)
|
|
19
|
+
- Migrate between recipes (`nx g spoonfeeder:migrate-orm typeorm-postgres drizzle-postgres`)
|
|
20
|
+
|
|
21
|
+
## Decision
|
|
22
|
+
|
|
23
|
+
Explore Nx Generators as a second phase for recipe management. The current generate-and-own approach remains for project creation. Nx Generators would complement it for in-project modifications.
|
|
24
|
+
|
|
25
|
+
## Consequences
|
|
26
|
+
|
|
27
|
+
### Positive
|
|
28
|
+
|
|
29
|
+
- Teams can add recipes incrementally as needs evolve
|
|
30
|
+
- AST transforms safely modify imports, module registrations, and providers
|
|
31
|
+
- Nx's virtual filesystem stages changes atomically (all-or-nothing)
|
|
32
|
+
- Generators can run in dry-run mode for previewing changes
|
|
33
|
+
- Pairs naturally with our existing Nx support for monorepo/full-stack types
|
|
34
|
+
|
|
35
|
+
### Negative
|
|
36
|
+
|
|
37
|
+
- Significant development effort (AST manipulation is complex)
|
|
38
|
+
- Requires Nx as a project dependency (even for standalone apps)
|
|
39
|
+
- Must handle all ORM/framework variations in transform logic
|
|
40
|
+
- Testing generators requires snapshot testing of file transforms
|
|
41
|
+
|
|
42
|
+
### Implementation Approach
|
|
43
|
+
|
|
44
|
+
1. **Phase 1:** Recipe generators that add files + update package.json (no AST)
|
|
45
|
+
2. **Phase 2:** Smart generators that modify app.module.ts imports and registrations
|
|
46
|
+
3. **Phase 3:** Migration generators between recipes (e.g., TypeORM → Drizzle)
|
|
47
|
+
|
|
48
|
+
### Technology
|
|
49
|
+
|
|
50
|
+
- `@nx/devkit` — Generator API with Tree (virtual filesystem), `generateFiles`, `updateJson`
|
|
51
|
+
- `ts-morph` — TypeScript AST manipulation for modifying source files
|
|
52
|
+
- `@nx/nest` — Reference implementation for NestJS-specific generators
|
|
53
|
+
|
|
54
|
+
## Alternatives Considered
|
|
55
|
+
|
|
56
|
+
### Plop.js
|
|
57
|
+
|
|
58
|
+
- **Pros:** Simple, Handlebars templates, low learning curve
|
|
59
|
+
- **Cons:** Cannot modify existing files, only generates new ones
|
|
60
|
+
- **Why not:** Doesn't solve the core problem (modifying app.module.ts, package.json)
|
|
61
|
+
|
|
62
|
+
### Custom AST scripts
|
|
63
|
+
|
|
64
|
+
- **Pros:** No framework dependency
|
|
65
|
+
- **Cons:** Reimplements what Nx already provides (virtual filesystem, atomic commits, dry-run)
|
|
66
|
+
- **Why not:** Nx is already in our stack for monorepo/full-stack types
|
|
67
|
+
|
|
68
|
+
## References
|
|
69
|
+
|
|
70
|
+
- [Nx Generator Documentation](https://nx.dev/extending-nx/intro/getting-started)
|
|
71
|
+
- [@nx/devkit API](https://nx.dev/nx-api/devkit)
|
|
72
|
+
- [ts-morph](https://ts-morph.com/)
|
|
73
|
+
- [Creating Custom Nx Generators](https://blog.nrwl.io/create-a-custom-nx-workspace-generator-5a915d845fd)
|