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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BBJ Systems Holding
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src=".github/banner.svg" alt="spoonfeeder" width="100%" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://www.npmjs.com/package/spoonfeeder"><img src="https://img.shields.io/npm/v/spoonfeeder?style=flat-square" alt="npm version" /></a>
|
|
7
|
+
<a href="https://www.npmjs.com/package/spoonfeeder"><img src="https://img.shields.io/npm/dm/spoonfeeder?style=flat-square" alt="npm downloads" /></a>
|
|
8
|
+
<a href="https://github.com/bbjansen/spoonfeeder/blob/main/LICENSE"><img src="https://img.shields.io/github/license/bbjansen/spoonfeeder?style=flat-square" alt="license" /></a>
|
|
9
|
+
<a href="https://nodejs.org/"><img src="https://img.shields.io/node/v/spoonfeeder?style=flat-square" alt="node version" /></a>
|
|
10
|
+
<a href="https://github.com/bbjansen/spoonfeeder/actions"><img src="https://img.shields.io/github/actions/workflow/status/bbjansen/spoonfeeder/ci.yml?style=flat-square&label=CI" alt="CI" /></a>
|
|
11
|
+
<a href="https://github.com/bbjansen/spoonfeeder/blob/main/docs/contributing.md"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen?style=flat-square" alt="PRs welcome" /></a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<p align="center">
|
|
15
|
+
<img src="https://img.shields.io/badge/NestJS-E0234E?style=for-the-badge&logo=nestjs&logoColor=white" alt="NestJS" />
|
|
16
|
+
<img src="https://img.shields.io/badge/Fastify-000000?style=for-the-badge&logo=fastify&logoColor=white" alt="Fastify" />
|
|
17
|
+
<img src="https://img.shields.io/badge/TypeScript-3178C6?style=for-the-badge&logo=typescript&logoColor=white" alt="TypeScript" />
|
|
18
|
+
<img src="https://img.shields.io/badge/Node.js-5FA04E?style=for-the-badge&logo=nodedotjs&logoColor=white" alt="Node.js" />
|
|
19
|
+
<img src="https://img.shields.io/badge/AWS-232F3E?style=for-the-badge&logo=amazonwebservices&logoColor=white" alt="AWS" />
|
|
20
|
+
<img src="https://img.shields.io/badge/Google%20Cloud-4285F4?style=for-the-badge&logo=googlecloud&logoColor=white" alt="Google Cloud" />
|
|
21
|
+
<img src="https://img.shields.io/badge/Azure-0078D4?style=for-the-badge&logo=microsoftazure&logoColor=white" alt="Azure" />
|
|
22
|
+
<img src="https://img.shields.io/badge/Docker-2496ED?style=for-the-badge&logo=docker&logoColor=white" alt="Docker" />
|
|
23
|
+
<img src="https://img.shields.io/badge/PostgreSQL-4169E1?style=for-the-badge&logo=postgresql&logoColor=white" alt="PostgreSQL" />
|
|
24
|
+
<img src="https://img.shields.io/badge/MongoDB-47A248?style=for-the-badge&logo=mongodb&logoColor=white" alt="MongoDB" />
|
|
25
|
+
<img src="https://img.shields.io/badge/Redis-FF4438?style=for-the-badge&logo=redis&logoColor=white" alt="Redis" />
|
|
26
|
+
<img src="https://img.shields.io/badge/GraphQL-E10098?style=for-the-badge&logo=graphql&logoColor=white" alt="GraphQL" />
|
|
27
|
+
<img src="https://img.shields.io/badge/Prisma-2D3748?style=for-the-badge&logo=prisma&logoColor=white" alt="Prisma" />
|
|
28
|
+
<img src="https://img.shields.io/badge/Nx-143055?style=for-the-badge&logo=nx&logoColor=white" alt="Nx" />
|
|
29
|
+
<img src="https://img.shields.io/badge/Swagger-85EA2D?style=for-the-badge&logo=swagger&logoColor=black" alt="Swagger" />
|
|
30
|
+
<img src="https://img.shields.io/badge/Jest-C21325?style=for-the-badge&logo=jest&logoColor=white" alt="Jest" />
|
|
31
|
+
<img src="https://img.shields.io/badge/RabbitMQ-FF6600?style=for-the-badge&logo=rabbitmq&logoColor=white" alt="RabbitMQ" />
|
|
32
|
+
<img src="https://img.shields.io/badge/Apache%20Kafka-231F20?style=for-the-badge&logo=apachekafka&logoColor=white" alt="Kafka" />
|
|
33
|
+
<img src="https://img.shields.io/badge/Kubernetes-326CE5?style=for-the-badge&logo=kubernetes&logoColor=white" alt="Kubernetes" />
|
|
34
|
+
<img src="https://img.shields.io/badge/Terraform-844FBA?style=for-the-badge&logo=terraform&logoColor=white" alt="Terraform" />
|
|
35
|
+
<img src="https://img.shields.io/badge/OpenTelemetry-000000?style=for-the-badge&logo=opentelemetry&logoColor=white" alt="OpenTelemetry" />
|
|
36
|
+
<img src="https://img.shields.io/badge/Prometheus-E6522C?style=for-the-badge&logo=prometheus&logoColor=white" alt="Prometheus" />
|
|
37
|
+
<img src="https://img.shields.io/badge/Sentry-362D59?style=for-the-badge&logo=sentry&logoColor=white" alt="Sentry" />
|
|
38
|
+
</p>
|
|
39
|
+
|
|
40
|
+
<p align="center">
|
|
41
|
+
<img src="https://img.shields.io/badge/Claude_Code-CC9B7A?style=for-the-badge&logo=anthropic&logoColor=white" alt="Claude Code" />
|
|
42
|
+
<img src="https://img.shields.io/badge/Cursor-000000?style=for-the-badge&logo=cursor&logoColor=white" alt="Cursor" />
|
|
43
|
+
<img src="https://img.shields.io/badge/GitHub_Copilot-000000?style=for-the-badge&logo=githubcopilot&logoColor=white" alt="GitHub Copilot" />
|
|
44
|
+
</p>
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
Interactive CLI that scaffolds production-ready, AI-friendly NestJS projects with 112 composable recipes. Pick a project type, choose your stack, and get a working codebase with structured error handling, test scaffolds, AI assistant context, and deployment configs — ready to ship, not "just fill in the rest yourself."
|
|
49
|
+
|
|
50
|
+
## Quick Start
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npx spoonfeeder
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Or with pnpm:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pnpm dlx spoonfeeder
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
One command. The CLI walks you through project name, type, cloud provider, and recipe selection, then generates everything to disk.
|
|
63
|
+
|
|
64
|
+
## What It Looks Like
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
┌ spoonfeeder — NestJS Project Generator
|
|
68
|
+
│
|
|
69
|
+
◇ Project name
|
|
70
|
+
│ my-api
|
|
71
|
+
│
|
|
72
|
+
◆ Project type
|
|
73
|
+
│ ● HTTP REST API (Fastify)
|
|
74
|
+
│ ○ AWS Lambda
|
|
75
|
+
│ ○ Microservice
|
|
76
|
+
│ ○ CLI Application
|
|
77
|
+
│ ○ Scheduled Worker
|
|
78
|
+
│ ○ Monorepo (Nx)
|
|
79
|
+
│ ○ Full-Stack
|
|
80
|
+
│
|
|
81
|
+
◇ Cloud provider
|
|
82
|
+
│ AWS
|
|
83
|
+
│
|
|
84
|
+
◆ Select recipes
|
|
85
|
+
│ ◼ TypeORM + PostgreSQL
|
|
86
|
+
│ ◼ JWT Authentication
|
|
87
|
+
│ ◼ Swagger / OpenAPI
|
|
88
|
+
│ ◼ Pino Logging
|
|
89
|
+
│ ◼ Health Checks
|
|
90
|
+
│ ◼ Helmet Security Headers
|
|
91
|
+
│ ◻ Rate Limiting
|
|
92
|
+
│ ◻ CORS
|
|
93
|
+
│ ◻ OpenTelemetry
|
|
94
|
+
│ ◻ Prometheus
|
|
95
|
+
│ ... 103 more available
|
|
96
|
+
│
|
|
97
|
+
◇ Confirm
|
|
98
|
+
│ Project: my-api
|
|
99
|
+
│ Type: HTTP REST API
|
|
100
|
+
│ Cloud: AWS
|
|
101
|
+
│ Add-ons: typeorm-postgres, jwt-auth, swagger, pino, health-checks, helmet
|
|
102
|
+
│ Directory: ./my-api
|
|
103
|
+
│
|
|
104
|
+
◒ Creating project structure...
|
|
105
|
+
│
|
|
106
|
+
◇ Project structure created.
|
|
107
|
+
│
|
|
108
|
+
│ Next steps
|
|
109
|
+
│ cd my-api
|
|
110
|
+
│ pnpm start:dev
|
|
111
|
+
│
|
|
112
|
+
└ Project created successfully!
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Project Types
|
|
116
|
+
|
|
117
|
+
Seven project archetypes, each with tailored defaults, directory structure, and compatible recipe sets:
|
|
118
|
+
|
|
119
|
+
| Type | Description |
|
|
120
|
+
| ------------------ | ------------------------------------------------------------ |
|
|
121
|
+
| HTTP REST API | Fastify adapter with validation, Swagger, and error handling |
|
|
122
|
+
| AWS Lambda | Serverless handler configured for Lambda deployments |
|
|
123
|
+
| Microservice | Event-driven service with transport layer (TCP, NATS, etc.) |
|
|
124
|
+
| CLI Application | Command-line tool built on nest-commander |
|
|
125
|
+
| Scheduled Worker | Cron-based background jobs with @nestjs/schedule |
|
|
126
|
+
| Monorepo | Nx workspace with shared libraries and code generators |
|
|
127
|
+
| Full-Stack | NestJS backend + frontend (Next.js, Vite, Nuxt, SvelteKit) |
|
|
128
|
+
|
|
129
|
+
## Recipe Categories
|
|
130
|
+
|
|
131
|
+
| Category | Count | Examples |
|
|
132
|
+
| ---------------- | ----: | ----------------------------------------------------- |
|
|
133
|
+
| API Patterns | 15 | Pagination, versioning, JSON Patch, SSE, i18n |
|
|
134
|
+
| Cloud — AWS | 12 | SQS, SNS, S3, DynamoDB, Cognito, EventBridge |
|
|
135
|
+
| Auth | 11 | JWT, Passport, OAuth, RBAC, MFA, DPoP |
|
|
136
|
+
| Database | 10 | TypeORM, Prisma, Drizzle, MikroORM, Mongoose, Kysely |
|
|
137
|
+
| Cloud — GCP | 10 | Pub/Sub, Cloud SQL, Firestore, Cloud Functions |
|
|
138
|
+
| Cloud — Azure | 10 | Service Bus, Cosmos DB, Blob Storage, Functions |
|
|
139
|
+
| Developer XP | 7 | DevContainers, feature flags, circuit breaker |
|
|
140
|
+
| Security | 6 | Helmet, CORS, CSRF, throttling, data masking |
|
|
141
|
+
| Operational | 5 | Graceful shutdown, multi-tenancy, worker threads |
|
|
142
|
+
| Repo Hygiene | 4 | Changelog, license headers, Dependabot/Renovate |
|
|
143
|
+
| Observability | 3 | OpenTelemetry, distributed tracing, request logging |
|
|
144
|
+
| Queues | 3 | RabbitMQ, BullMQ, dead letter queues |
|
|
145
|
+
| Monitoring | 2 | Health checks, Prometheus |
|
|
146
|
+
| Logging | 2 | Pino, Winston |
|
|
147
|
+
| Error Tracking | 2 | Sentry, Seq |
|
|
148
|
+
| Email | 2 | Nodemailer, SendGrid |
|
|
149
|
+
| + 8 more | 8 | WebSockets, GraphQL, CQRS, Storage, Testing, Docs |
|
|
150
|
+
| **Total** | **112** | |
|
|
151
|
+
|
|
152
|
+
Each recipe ships its own dependencies, environment variables, configuration module, source files, tests, and AI context. Recipes declare conflicts and requirements explicitly, so the CLI rejects incompatible combinations before anything hits disk.
|
|
153
|
+
|
|
154
|
+
### Highlighted Recipes
|
|
155
|
+
|
|
156
|
+
**Database** — TypeORM (Postgres, MySQL), Prisma, Drizzle, MikroORM, Mongoose, Kysely, Redis, database seeding, database factories
|
|
157
|
+
|
|
158
|
+
**Auth** — JWT, Passport strategies, API keys, RBAC via CASL, OAuth2 introspection, OAuth providers (Google, GitHub, Apple), MFA/TOTP, DPoP (RFC 9449)
|
|
159
|
+
|
|
160
|
+
**Cloud** — Full recipe sets for AWS (SQS, SNS, S3, EventBridge, DynamoDB, Cognito, Secrets Manager, and more), GCP (Pub/Sub, Cloud SQL, Firestore, Cloud Functions), and Azure (Service Bus, Cosmos DB, Blob Storage, Functions)
|
|
161
|
+
|
|
162
|
+
**API Patterns** — Pagination, filtering, API versioning, HTTP caching (RFC 9111), JSON Patch (RFC 6902), Prefer header (RFC 7240), Content Digest (RFC 9530), SSE, soft delete, audit trail, i18n
|
|
163
|
+
|
|
164
|
+
**Observability** — OpenTelemetry, distributed tracing, Prometheus metrics, structured request logging with correlation IDs
|
|
165
|
+
|
|
166
|
+
## AI-Ready Projects
|
|
167
|
+
|
|
168
|
+
Every generated project ships with AI assistant context tailored to your exact stack. When you select recipes, spoonfeeder generates project-specific instructions for three major AI coding assistants:
|
|
169
|
+
|
|
170
|
+
| File | Assistant | What it contains |
|
|
171
|
+
|------|-----------|-----------------|
|
|
172
|
+
| `CLAUDE.md` | Claude Code | Project architecture, selected recipes, testing conventions, error patterns, available commands |
|
|
173
|
+
| `.cursor/rules/project.mdc` | Cursor | Combined rules for all selected recipes with usage patterns and constraints |
|
|
174
|
+
| `.github/copilot-instructions.md` | GitHub Copilot | Stack overview, coding standards, recipe-specific guidance |
|
|
175
|
+
|
|
176
|
+
The AI context is not generic boilerplate — it reflects the specific recipes you selected. If you pick TypeORM + PostgreSQL + JWT Auth + Swagger, the generated `CLAUDE.md` describes those exact integrations, how they're wired, and how to extend them. Your AI assistant understands your project from the first prompt.
|
|
177
|
+
|
|
178
|
+
When you add or remove recipes post-scaffolding via Nx generators, the AI context files are updated automatically.
|
|
179
|
+
|
|
180
|
+
## What You Get
|
|
181
|
+
|
|
182
|
+
Every generated project includes:
|
|
183
|
+
|
|
184
|
+
- **RFC 9457 error responses** — Typed error hierarchy with trace codes and Problem Details for HTTP APIs
|
|
185
|
+
- **Test scaffolds** — Unit, integration, and E2E test structure with shared factories and per-recipe test files
|
|
186
|
+
- **Exact dependency versions** — No `^`, no `~`, no supply-chain surprises. Every version is pinned.
|
|
187
|
+
- **Husky + commitlint + lint-staged** — Conventional commits and code formatting enforced from the first commit
|
|
188
|
+
- **Per-environment configs** — Separate `.env` files for development, test, and production with recipe-specific variables
|
|
189
|
+
- **Docker Compose** — Dev-ready container setup for databases, caches, and message brokers matching your recipes
|
|
190
|
+
- **Nx generators** — Add, remove, or migrate recipes after scaffolding without manual wiring
|
|
191
|
+
- **CI/CD templates** — GitHub Actions workflows for test, lint, build, and deploy
|
|
192
|
+
|
|
193
|
+
No runtime dependency on spoonfeeder. The generated project is a standard NestJS application. Eject and own your code from day one.
|
|
194
|
+
|
|
195
|
+
### How It Works
|
|
196
|
+
|
|
197
|
+
1. **Run the CLI** — Answer a few prompts: project name, type, cloud provider, recipes
|
|
198
|
+
2. **Recipes resolve** — Dependencies, conflicts, and requirements are validated automatically
|
|
199
|
+
3. **Project generates** — Source files, configs, environment variables, tests, and AI context are written to disk
|
|
200
|
+
4. **Start building** — `cd` into the project, install, and run `pnpm start:dev`
|
|
201
|
+
|
|
202
|
+
## Post-Scaffolding (Nx Generators)
|
|
203
|
+
|
|
204
|
+
Recipes are not frozen at scaffolding time. Spoonfeeder ships Nx generators so you can evolve your stack after project creation:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
# Add a recipe to an existing project
|
|
208
|
+
nx g spoonfeeder:add --recipe=swagger
|
|
209
|
+
|
|
210
|
+
# Remove a recipe cleanly (deps, config, source files, tests)
|
|
211
|
+
nx g spoonfeeder:remove --recipe=swagger
|
|
212
|
+
|
|
213
|
+
# Migrate between compatible recipes
|
|
214
|
+
nx g spoonfeeder:migrate --from=typeorm-postgres --to=prisma
|
|
215
|
+
|
|
216
|
+
# List all available and installed recipes
|
|
217
|
+
nx g spoonfeeder:list
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Add what you need, remove what you don't. No lock-in.
|
|
221
|
+
|
|
222
|
+
## Documentation
|
|
223
|
+
|
|
224
|
+
Full docs at **[bbjansen.github.io/spoonfeeder](https://bbjansen.github.io/spoonfeeder/)**
|
|
225
|
+
|
|
226
|
+
| Section | What it covers |
|
|
227
|
+
| ------- | -------------- |
|
|
228
|
+
| [Quick Start](https://bbjansen.github.io/spoonfeeder/getting-started/quick-start/) | Installation, CLI walkthrough, generated structure |
|
|
229
|
+
| [Project Types](https://bbjansen.github.io/spoonfeeder/getting-started/project-types/) | Deep dive into each of the 7 archetypes |
|
|
230
|
+
| [Recipe Catalog](https://bbjansen.github.io/spoonfeeder/recipes/all/) | Full list of all 112 recipes with dependencies |
|
|
231
|
+
| [Nx Generators](https://bbjansen.github.io/spoonfeeder/generators/) | Add, remove, migrate, and list recipes |
|
|
232
|
+
| [Architecture](https://bbjansen.github.io/spoonfeeder/architecture/) | Generator pipeline, error handling, standards |
|
|
233
|
+
|
|
234
|
+
## Requirements
|
|
235
|
+
|
|
236
|
+
- Node.js >= 22.0.0
|
|
237
|
+
- pnpm >= 9.0.0 (recommended) or npm
|
|
238
|
+
|
|
239
|
+
## Contributing
|
|
240
|
+
|
|
241
|
+
Contributions welcome. See [docs/contributing.md](docs/contributing.md) for setup instructions, branch naming conventions, and the development workflow.
|
|
242
|
+
|
|
243
|
+
## Author
|
|
244
|
+
|
|
245
|
+
**B.B. Jansen** — [github.com/bbjansen](https://github.com/bbjansen)
|
|
246
|
+
|
|
247
|
+
## License
|
|
248
|
+
|
|
249
|
+
MIT — BBJ Systems Holding
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { RecipeDefinition, ProjectConfig } from '../types.js';
|
|
2
|
+
export declare function assembleClaudeMd(outputDir: string, config: ProjectConfig, recipes: RecipeDefinition[]): Promise<void>;
|
|
3
|
+
export declare function assembleCursorRules(outputDir: string, recipes: RecipeDefinition[]): Promise<void>;
|
|
4
|
+
export declare function assembleCopilotInstructions(outputDir: string, recipes: RecipeDefinition[]): Promise<void>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
export async function assembleClaudeMd(outputDir, config, recipes) {
|
|
4
|
+
const sections = [
|
|
5
|
+
'# CLAUDE.md',
|
|
6
|
+
'',
|
|
7
|
+
'## Package Manager',
|
|
8
|
+
'',
|
|
9
|
+
'Always use **pnpm**. Never use npm or yarn.',
|
|
10
|
+
'',
|
|
11
|
+
'## Imports',
|
|
12
|
+
'',
|
|
13
|
+
'Use the `@/*` alias for all internal imports — it maps to `src/*`.',
|
|
14
|
+
'',
|
|
15
|
+
`## Project Type`,
|
|
16
|
+
'',
|
|
17
|
+
`This is a ${config.projectType} project.`,
|
|
18
|
+
'',
|
|
19
|
+
];
|
|
20
|
+
if (recipes.length > 0) {
|
|
21
|
+
sections.push('## Active Recipes', '');
|
|
22
|
+
for (const recipe of recipes) {
|
|
23
|
+
sections.push(`- **${recipe.name}** — ${recipe.description}`);
|
|
24
|
+
}
|
|
25
|
+
sections.push('');
|
|
26
|
+
}
|
|
27
|
+
for (const recipe of recipes) {
|
|
28
|
+
if (recipe.claudeMdSection) {
|
|
29
|
+
sections.push(recipe.claudeMdSection, '');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
await fs.writeFile(path.join(outputDir, 'CLAUDE.md'), sections.join('\n'), 'utf-8');
|
|
33
|
+
}
|
|
34
|
+
export async function assembleCursorRules(outputDir, recipes) {
|
|
35
|
+
const rules = recipes.filter((r) => r.cursorRules).map((r) => r.cursorRules);
|
|
36
|
+
if (rules.length === 0)
|
|
37
|
+
return;
|
|
38
|
+
const cursorDir = path.join(outputDir, '.cursor', 'rules');
|
|
39
|
+
await fs.ensureDir(cursorDir);
|
|
40
|
+
await fs.writeFile(path.join(cursorDir, 'project.mdc'), rules.join('\n\n'), 'utf-8');
|
|
41
|
+
}
|
|
42
|
+
export async function assembleCopilotInstructions(outputDir, recipes) {
|
|
43
|
+
const instructions = recipes
|
|
44
|
+
.filter((r) => r.copilotInstructions)
|
|
45
|
+
.map((r) => r.copilotInstructions);
|
|
46
|
+
if (instructions.length === 0)
|
|
47
|
+
return;
|
|
48
|
+
const githubDir = path.join(outputDir, '.github');
|
|
49
|
+
await fs.ensureDir(githubDir);
|
|
50
|
+
await fs.writeFile(path.join(githubDir, 'copilot-instructions.md'), instructions.join('\n\n'), 'utf-8');
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=ai-context-assembler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-context-assembler.js","sourceRoot":"","sources":["../../src/generator/ai-context-assembler.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,UAAU,CAAC;AAG1B,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAAiB,EACjB,MAAqB,EACrB,OAA2B;IAE3B,MAAM,QAAQ,GAAG;QACf,aAAa;QACb,EAAE;QACF,oBAAoB;QACpB,EAAE;QACF,6CAA6C;QAC7C,EAAE;QACF,YAAY;QACZ,EAAE;QACF,oEAAoE;QACpE,EAAE;QACF,iBAAiB;QACjB,EAAE;QACF,aAAa,MAAM,CAAC,WAAW,WAAW;QAC1C,EAAE;KACH,CAAC;IAEF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,QAAQ,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;QACvC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,QAAQ,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,IAAI,QAAQ,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;QAChE,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpB,CAAC;IAED,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;YAC3B,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,SAAiB,EACjB,OAA2B;IAE3B,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAE7E,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAE/B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAC3D,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9B,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;AACvF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,SAAiB,EACjB,OAA2B;IAE3B,MAAM,YAAY,GAAG,OAAO;SACzB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC;SACpC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;IAErC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEtC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAClD,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9B,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,yBAAyB,CAAC,EAC/C,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,EACzB,OAAO,CACR,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function mergeEnvVars(base, additions) {
|
|
2
|
+
const merged = new Map();
|
|
3
|
+
for (const v of base) {
|
|
4
|
+
merged.set(v.key, v);
|
|
5
|
+
}
|
|
6
|
+
for (const group of additions) {
|
|
7
|
+
for (const v of group) {
|
|
8
|
+
merged.set(v.key, v);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return [...merged.values()];
|
|
12
|
+
}
|
|
13
|
+
export function renderEnvFile(vars) {
|
|
14
|
+
return vars.map((v) => `# ${v.description}\n${v.key}=${v.defaultValue}`).join('\n\n') + '\n';
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=env-merger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-merger.js","sourceRoot":"","sources":["../../src/generator/env-merger.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,YAAY,CAAC,IAAc,EAAE,SAAqB;IAChE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEzC,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACvB,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;QAC9B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAc;IAC1C,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;AAC/F,CAAC"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import * as p from '@clack/prompts';
|
|
4
|
+
import { renderTemplate } from './template-engine.js';
|
|
5
|
+
import { mergePackageJson } from './package-json-merger.js';
|
|
6
|
+
import { mergeEnvVars, renderEnvFile } from './env-merger.js';
|
|
7
|
+
import { assembleClaudeMd, assembleCursorRules, assembleCopilotInstructions, } from './ai-context-assembler.js';
|
|
8
|
+
import { insertBlockToString } from '../utils/main-ts-updater.js';
|
|
9
|
+
async function copyAndRenderDir(sourceDir, outputDir, data, skipDirs = [], baseOutputDir) {
|
|
10
|
+
const base = baseOutputDir ?? outputDir;
|
|
11
|
+
const copiedFiles = [];
|
|
12
|
+
if (!(await fs.pathExists(sourceDir)))
|
|
13
|
+
return copiedFiles;
|
|
14
|
+
const entries = await fs.readdir(sourceDir, { withFileTypes: true });
|
|
15
|
+
for (const entry of entries) {
|
|
16
|
+
const sourcePath = path.join(sourceDir, entry.name);
|
|
17
|
+
let outputName = entry.name;
|
|
18
|
+
// Handle dot-prefixed directories (dot-husky -> .husky)
|
|
19
|
+
if (entry.isDirectory()) {
|
|
20
|
+
if (skipDirs.includes(entry.name))
|
|
21
|
+
continue;
|
|
22
|
+
if (outputName.startsWith('dot-')) {
|
|
23
|
+
outputName = '.' + outputName.slice(4);
|
|
24
|
+
}
|
|
25
|
+
const subFiles = await copyAndRenderDir(sourcePath, path.join(outputDir, outputName), data, skipDirs, base);
|
|
26
|
+
copiedFiles.push(...subFiles);
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
// Skip package fragments and READMEs (handled separately)
|
|
30
|
+
if (outputName === 'package-fragment.json' || outputName === 'README.md')
|
|
31
|
+
continue;
|
|
32
|
+
// Handle dot-prefixed files (dot-gitignore -> .gitignore)
|
|
33
|
+
if (outputName.startsWith('dot-')) {
|
|
34
|
+
outputName = '.' + outputName.slice(4);
|
|
35
|
+
}
|
|
36
|
+
if (outputName.endsWith('.ejs')) {
|
|
37
|
+
outputName = outputName.replace(/\.ejs$/, '');
|
|
38
|
+
const template = await fs.readFile(sourcePath, 'utf-8');
|
|
39
|
+
const rendered = renderTemplate(template, data, sourcePath);
|
|
40
|
+
await fs.ensureDir(outputDir);
|
|
41
|
+
await fs.writeFile(path.join(outputDir, outputName), rendered, 'utf-8');
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
await fs.ensureDir(outputDir);
|
|
45
|
+
await fs.copy(sourcePath, path.join(outputDir, outputName));
|
|
46
|
+
}
|
|
47
|
+
copiedFiles.push(path.relative(base, path.join(outputDir, outputName)));
|
|
48
|
+
}
|
|
49
|
+
return copiedFiles;
|
|
50
|
+
}
|
|
51
|
+
export async function generate(config, registry, templatesDir) {
|
|
52
|
+
const { outputDir } = config;
|
|
53
|
+
const s = p.spinner();
|
|
54
|
+
s.start('Creating project structure...');
|
|
55
|
+
const dirExistedBefore = await fs.pathExists(outputDir);
|
|
56
|
+
try {
|
|
57
|
+
await fs.ensureDir(outputDir);
|
|
58
|
+
const templateData = {
|
|
59
|
+
name: config.name,
|
|
60
|
+
packageScope: config.scope,
|
|
61
|
+
projectType: config.projectType,
|
|
62
|
+
cloudProvider: config.cloudProvider,
|
|
63
|
+
transportLayer: config.transportLayer,
|
|
64
|
+
frontendFramework: config.frontendFramework,
|
|
65
|
+
};
|
|
66
|
+
// 1. Copy and render base templates
|
|
67
|
+
await copyAndRenderDir(path.join(templatesDir, 'base'), outputDir, templateData);
|
|
68
|
+
// 2. Overlay project-type-specific templates (skip frontend/ — handled in step 2c)
|
|
69
|
+
const projectTypeDir = path.join(templatesDir, 'project-types', config.projectType);
|
|
70
|
+
await copyAndRenderDir(projectTypeDir, outputDir, templateData, ['frontend']);
|
|
71
|
+
// 2c. Copy frontend framework for full-stack projects
|
|
72
|
+
if (config.projectType === 'full-stack' && config.frontendFramework) {
|
|
73
|
+
const frontendDir = path.join(templatesDir, 'project-types', 'full-stack', 'frontend', config.frontendFramework);
|
|
74
|
+
await copyAndRenderDir(frontendDir, path.join(outputDir, 'apps', 'web'), templateData);
|
|
75
|
+
}
|
|
76
|
+
// 2d. Relocate base template files for workspace project types (full-stack, monorepo)
|
|
77
|
+
// The base template copies NestJS source to root src/ and tests/, but these
|
|
78
|
+
// project types keep the NestJS app under apps/api/.
|
|
79
|
+
if (config.projectType === 'full-stack' || config.projectType === 'monorepo') {
|
|
80
|
+
const apiDir = path.join(outputDir, 'apps', 'api');
|
|
81
|
+
await fs.ensureDir(apiDir);
|
|
82
|
+
// Move src/ contents into apps/api/src/ (project-type already placed main.ts and app.module.ts there)
|
|
83
|
+
const rootSrcDir = path.join(outputDir, 'src');
|
|
84
|
+
const apiSrcDir = path.join(apiDir, 'src');
|
|
85
|
+
if (await fs.pathExists(rootSrcDir)) {
|
|
86
|
+
await fs.ensureDir(apiSrcDir);
|
|
87
|
+
const srcEntries = await fs.readdir(rootSrcDir, { withFileTypes: true });
|
|
88
|
+
for (const entry of srcEntries) {
|
|
89
|
+
const srcPath = path.join(rootSrcDir, entry.name);
|
|
90
|
+
const destPath = path.join(apiSrcDir, entry.name);
|
|
91
|
+
// Skip files already provided by the project-type template (main.ts, app.module.ts)
|
|
92
|
+
if (await fs.pathExists(destPath))
|
|
93
|
+
continue;
|
|
94
|
+
await fs.move(srcPath, destPath);
|
|
95
|
+
}
|
|
96
|
+
await fs.remove(rootSrcDir);
|
|
97
|
+
}
|
|
98
|
+
// Move tests/ into apps/api/tests/
|
|
99
|
+
const rootTestsDir = path.join(outputDir, 'tests');
|
|
100
|
+
const apiTestsDir = path.join(apiDir, 'tests');
|
|
101
|
+
if (await fs.pathExists(rootTestsDir)) {
|
|
102
|
+
await fs.move(rootTestsDir, apiTestsDir, { overwrite: true });
|
|
103
|
+
}
|
|
104
|
+
// Move nest-cli.json into apps/api/ and update sourceRoot
|
|
105
|
+
const rootNestCli = path.join(outputDir, 'nest-cli.json');
|
|
106
|
+
if (await fs.pathExists(rootNestCli)) {
|
|
107
|
+
const nestCliJson = (await fs.readJson(rootNestCli));
|
|
108
|
+
nestCliJson.sourceRoot = 'src';
|
|
109
|
+
await fs.writeJson(path.join(apiDir, 'nest-cli.json'), nestCliJson, { spaces: 2 });
|
|
110
|
+
await fs.remove(rootNestCli);
|
|
111
|
+
}
|
|
112
|
+
// Update jest.config.ts paths for workspace layout (tests and src under apps/api/)
|
|
113
|
+
const rootJestConfig = path.join(outputDir, 'jest.config.ts');
|
|
114
|
+
if (await fs.pathExists(rootJestConfig)) {
|
|
115
|
+
let jestContent = await fs.readFile(rootJestConfig, 'utf-8');
|
|
116
|
+
jestContent = jestContent
|
|
117
|
+
.replace(/<rootDir>\/tests\//g, '<rootDir>/apps/api/tests/')
|
|
118
|
+
.replace(/<rootDir>\/src\//g, '<rootDir>/apps/api/src/')
|
|
119
|
+
.replace(/collectCoverageFrom:\s*\['src\//g, "collectCoverageFrom: ['apps/api/src/")
|
|
120
|
+
.replace("'!src/**/*.spec.ts'", "'!apps/api/src/**/*.spec.ts'")
|
|
121
|
+
.replace("'!src/main.ts'", "'!apps/api/src/main.ts'");
|
|
122
|
+
await fs.writeFile(rootJestConfig, jestContent, 'utf-8');
|
|
123
|
+
}
|
|
124
|
+
// Update tsconfig.json paths: @/* -> apps/api/src/*
|
|
125
|
+
const rootTsConfig = path.join(outputDir, 'tsconfig.json');
|
|
126
|
+
if (await fs.pathExists(rootTsConfig)) {
|
|
127
|
+
const tsConfig = (await fs.readJson(rootTsConfig));
|
|
128
|
+
const compilerOptions = tsConfig.compilerOptions;
|
|
129
|
+
if (compilerOptions?.paths) {
|
|
130
|
+
compilerOptions.paths = { '@/*': ['apps/api/src/*'] };
|
|
131
|
+
}
|
|
132
|
+
await fs.writeJson(rootTsConfig, tsConfig, { spaces: 2 });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// 2b. Load project-type package fragment
|
|
136
|
+
const projectTypeFragmentPath = path.join(projectTypeDir, 'package-fragment.json');
|
|
137
|
+
const projectTypeFragment = (await fs.pathExists(projectTypeFragmentPath))
|
|
138
|
+
? (await fs.readJson(projectTypeFragmentPath))
|
|
139
|
+
: undefined;
|
|
140
|
+
// 3. Collect recipe definitions
|
|
141
|
+
const selectedRecipes = [];
|
|
142
|
+
for (const recipeId of config.recipes) {
|
|
143
|
+
const recipe = registry.get(recipeId);
|
|
144
|
+
if (recipe) {
|
|
145
|
+
selectedRecipes.push(recipe);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
p.log.warning(`Recipe '${recipeId}' not found in registry, skipping.`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// 4. Copy recipe template directories (track files per recipe for manifest)
|
|
152
|
+
// For workspace projects (full-stack, monorepo), recipe src/ and tests/ go under apps/api/
|
|
153
|
+
const isWorkspaceProject = config.projectType === 'full-stack' || config.projectType === 'monorepo';
|
|
154
|
+
const recipeOutputDir = isWorkspaceProject
|
|
155
|
+
? path.join(outputDir, 'apps', 'api')
|
|
156
|
+
: outputDir;
|
|
157
|
+
const recipeFilesMap = new Map();
|
|
158
|
+
for (const recipe of selectedRecipes) {
|
|
159
|
+
if (recipe.templateDir) {
|
|
160
|
+
const recipeTemplateDir = path.join(templatesDir, 'recipes', recipe.templateDir);
|
|
161
|
+
const files = await copyAndRenderDir(recipeTemplateDir, recipeOutputDir, templateData);
|
|
162
|
+
recipeFilesMap.set(recipe.id, files);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// 4b. Apply recipe main.ts blocks
|
|
166
|
+
const mainTsPath = isWorkspaceProject
|
|
167
|
+
? path.join(outputDir, 'apps', 'api', 'src', 'main.ts')
|
|
168
|
+
: path.join(outputDir, 'src', 'main.ts');
|
|
169
|
+
const appliedMainTsBlocks = new Set();
|
|
170
|
+
if (await fs.pathExists(mainTsPath)) {
|
|
171
|
+
let mainTsContent = await fs.readFile(mainTsPath, 'utf-8');
|
|
172
|
+
for (const recipe of selectedRecipes) {
|
|
173
|
+
if (recipe.mainTsSetup) {
|
|
174
|
+
mainTsContent = insertBlockToString(mainTsContent, recipe.mainTsSetup.blockId, recipe.mainTsSetup.block);
|
|
175
|
+
appliedMainTsBlocks.add(recipe.id);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
await fs.writeFile(mainTsPath, mainTsContent, 'utf-8');
|
|
179
|
+
}
|
|
180
|
+
// 5. Copy deployment templates
|
|
181
|
+
for (const target of config.deploymentTargets) {
|
|
182
|
+
const deployDir = path.join(templatesDir, 'recipes', 'deploy', target);
|
|
183
|
+
await copyAndRenderDir(deployDir, outputDir, templateData);
|
|
184
|
+
}
|
|
185
|
+
// 6. Copy CI/CD templates
|
|
186
|
+
if (config.ciCdProvider) {
|
|
187
|
+
const ciCdDir = path.join(templatesDir, 'recipes', 'ci-cd', config.ciCdProvider);
|
|
188
|
+
await copyAndRenderDir(ciCdDir, outputDir, templateData);
|
|
189
|
+
}
|
|
190
|
+
// 7. Merge package.json with project-type and recipe fragments
|
|
191
|
+
const basePackageJson = (await fs.readJson(path.join(outputDir, 'package.json')));
|
|
192
|
+
const fragments = [
|
|
193
|
+
...(projectTypeFragment
|
|
194
|
+
? [
|
|
195
|
+
{
|
|
196
|
+
dependencies: projectTypeFragment.dependencies ?? {},
|
|
197
|
+
devDependencies: projectTypeFragment.devDependencies ?? {},
|
|
198
|
+
},
|
|
199
|
+
]
|
|
200
|
+
: []),
|
|
201
|
+
...selectedRecipes.map((r) => ({
|
|
202
|
+
dependencies: r.dependencies,
|
|
203
|
+
devDependencies: r.devDependencies,
|
|
204
|
+
})),
|
|
205
|
+
];
|
|
206
|
+
const mergedPackageJson = mergePackageJson(basePackageJson, fragments);
|
|
207
|
+
await fs.writeJson(path.join(outputDir, 'package.json'), mergedPackageJson, {
|
|
208
|
+
spaces: 2,
|
|
209
|
+
});
|
|
210
|
+
// 8. Merge env vars
|
|
211
|
+
const baseEnvVars = [
|
|
212
|
+
{ key: 'PORT', defaultValue: '3000', description: 'HTTP port' },
|
|
213
|
+
{ key: 'NODE_ENV', defaultValue: 'development', description: 'Environment' },
|
|
214
|
+
];
|
|
215
|
+
const recipeEnvVars = selectedRecipes.map((r) => r.envVars);
|
|
216
|
+
const mergedEnvVars = mergeEnvVars(baseEnvVars, recipeEnvVars);
|
|
217
|
+
await fs.writeFile(path.join(outputDir, '.env.example'), renderEnvFile(mergedEnvVars), 'utf-8');
|
|
218
|
+
// 9. Assemble AI context
|
|
219
|
+
await assembleClaudeMd(outputDir, config, selectedRecipes);
|
|
220
|
+
await assembleCursorRules(outputDir, selectedRecipes);
|
|
221
|
+
await assembleCopilotInstructions(outputDir, selectedRecipes);
|
|
222
|
+
// 10. Create .spoonfeeder.json manifest
|
|
223
|
+
const manifest = {
|
|
224
|
+
projectType: config.projectType,
|
|
225
|
+
cloudProvider: config.cloudProvider,
|
|
226
|
+
spoonfeederVersion: '0.0.1',
|
|
227
|
+
generatedAt: new Date().toISOString(),
|
|
228
|
+
recipes: Object.fromEntries(selectedRecipes.map((recipe) => {
|
|
229
|
+
return [
|
|
230
|
+
recipe.id,
|
|
231
|
+
{
|
|
232
|
+
installedAt: new Date().toISOString(),
|
|
233
|
+
version: '0.0.1',
|
|
234
|
+
files: recipeFilesMap.get(recipe.id) ?? [],
|
|
235
|
+
...(recipe.mainTsSetup &&
|
|
236
|
+
appliedMainTsBlocks.has(recipe.id) && {
|
|
237
|
+
mainTsBlocks: [recipe.mainTsSetup.blockId],
|
|
238
|
+
}),
|
|
239
|
+
},
|
|
240
|
+
];
|
|
241
|
+
})),
|
|
242
|
+
};
|
|
243
|
+
await fs.writeJson(path.join(outputDir, '.spoonfeeder.json'), manifest, { spaces: 2 });
|
|
244
|
+
s.stop('Project structure created.');
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
s.stop('Project generation failed.');
|
|
248
|
+
if (!dirExistedBefore)
|
|
249
|
+
await fs.remove(outputDir);
|
|
250
|
+
throw error;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/generator/generator.ts"],"names":[],"mappings":"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"}
|