@biggora/claude-plugins 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -4
- package/package.json +1 -1
- package/registry/registry.json +334 -244
- package/specs/coding.md +30 -0
- package/specs/pod.md +2 -0
- package/src/commands/skills/add.js +63 -7
- package/src/commands/skills/list.js +23 -52
- package/src/commands/skills/remove.js +26 -27
- package/src/commands/skills/resolve.js +155 -0
- package/src/commands/skills/update.js +58 -74
- package/src/skills/captcha/README.md +221 -0
- package/src/skills/captcha/SKILL.md +355 -0
- package/src/skills/captcha/references/captcha-types.md +254 -0
- package/src/skills/captcha/references/services.md +172 -0
- package/src/skills/captcha/references/stealth.md +238 -0
- package/src/skills/captcha/scripts/solve_captcha.py +323 -0
- package/src/skills/captcha/scripts/solve_image_grid.py +350 -0
- package/src/skills/google-merchant-api/SKILL.md +581 -0
- package/src/skills/google-merchant-api/references/accounts.md +247 -0
- package/src/skills/google-merchant-api/references/content-api-legacy.md +216 -0
- package/src/skills/google-merchant-api/references/datasources.md +233 -0
- package/src/skills/google-merchant-api/references/inventories.md +201 -0
- package/src/skills/google-merchant-api/references/migration.md +267 -0
- package/src/skills/google-merchant-api/references/products.md +316 -0
- package/src/skills/google-merchant-api/references/promotions.md +201 -0
- package/src/skills/google-merchant-api/references/reports.md +240 -0
- package/src/skills/lv-aggregators-api/SKILL.md +113 -0
- package/src/skills/lv-aggregators-api/references/integration-guide.md +368 -0
- package/src/skills/lv-aggregators-api/references/kurpirkt.md +103 -0
- package/src/skills/lv-aggregators-api/references/salidzini.md +122 -0
- package/src/skills/nest-best-practices/SKILL.md +251 -0
- package/src/skills/nest-best-practices/references/best-practices-request-lifecycle.md +158 -0
- package/src/skills/nest-best-practices/references/cli-monorepo.md +106 -0
- package/src/skills/nest-best-practices/references/cli-overview.md +157 -0
- package/src/skills/nest-best-practices/references/core-controllers.md +165 -0
- package/src/skills/nest-best-practices/references/core-dependency-injection.md +179 -0
- package/src/skills/nest-best-practices/references/core-middleware.md +139 -0
- package/src/skills/nest-best-practices/references/core-modules.md +138 -0
- package/src/skills/nest-best-practices/references/core-providers.md +188 -0
- package/src/skills/nest-best-practices/references/faq-raw-body-hybrid.md +122 -0
- package/src/skills/nest-best-practices/references/fundamentals-circular-dependency.md +89 -0
- package/src/skills/nest-best-practices/references/fundamentals-custom-decorators.md +107 -0
- package/src/skills/nest-best-practices/references/fundamentals-dynamic-modules.md +125 -0
- package/src/skills/nest-best-practices/references/fundamentals-exception-filters.md +202 -0
- package/src/skills/nest-best-practices/references/fundamentals-execution-context.md +107 -0
- package/src/skills/nest-best-practices/references/fundamentals-guards.md +136 -0
- package/src/skills/nest-best-practices/references/fundamentals-interceptors.md +187 -0
- package/src/skills/nest-best-practices/references/fundamentals-lazy-loading.md +89 -0
- package/src/skills/nest-best-practices/references/fundamentals-lifecycle-events.md +87 -0
- package/src/skills/nest-best-practices/references/fundamentals-module-reference.md +107 -0
- package/src/skills/nest-best-practices/references/fundamentals-pipes.md +197 -0
- package/src/skills/nest-best-practices/references/fundamentals-provider-scopes.md +92 -0
- package/src/skills/nest-best-practices/references/fundamentals-testing.md +142 -0
- package/src/skills/nest-best-practices/references/graphql-overview.md +233 -0
- package/src/skills/nest-best-practices/references/graphql-resolvers-mutations.md +199 -0
- package/src/skills/nest-best-practices/references/graphql-scalars-unions-enums.md +180 -0
- package/src/skills/nest-best-practices/references/graphql-subscriptions.md +228 -0
- package/src/skills/nest-best-practices/references/microservices-grpc.md +175 -0
- package/src/skills/nest-best-practices/references/microservices-overview.md +221 -0
- package/src/skills/nest-best-practices/references/microservices-transports.md +119 -0
- package/src/skills/nest-best-practices/references/openapi-swagger.md +207 -0
- package/src/skills/nest-best-practices/references/recipes-authentication.md +97 -0
- package/src/skills/nest-best-practices/references/recipes-cqrs.md +176 -0
- package/src/skills/nest-best-practices/references/recipes-crud-generator.md +87 -0
- package/src/skills/nest-best-practices/references/recipes-documentation.md +93 -0
- package/src/skills/nest-best-practices/references/recipes-mongoose.md +153 -0
- package/src/skills/nest-best-practices/references/recipes-prisma.md +98 -0
- package/src/skills/nest-best-practices/references/recipes-terminus.md +148 -0
- package/src/skills/nest-best-practices/references/recipes-typeorm.md +122 -0
- package/src/skills/nest-best-practices/references/security-authorization.md +196 -0
- package/src/skills/nest-best-practices/references/security-cors-helmet-rate-limiting.md +204 -0
- package/src/skills/nest-best-practices/references/security-encryption-hashing.md +93 -0
- package/src/skills/nest-best-practices/references/techniques-caching.md +142 -0
- package/src/skills/nest-best-practices/references/techniques-compression-streaming-sse.md +194 -0
- package/src/skills/nest-best-practices/references/techniques-configuration.md +132 -0
- package/src/skills/nest-best-practices/references/techniques-database.md +153 -0
- package/src/skills/nest-best-practices/references/techniques-events.md +163 -0
- package/src/skills/nest-best-practices/references/techniques-fastify.md +137 -0
- package/src/skills/nest-best-practices/references/techniques-file-upload.md +140 -0
- package/src/skills/nest-best-practices/references/techniques-http-module.md +176 -0
- package/src/skills/nest-best-practices/references/techniques-logging.md +146 -0
- package/src/skills/nest-best-practices/references/techniques-mvc-serve-static.md +132 -0
- package/src/skills/nest-best-practices/references/techniques-queues.md +162 -0
- package/src/skills/nest-best-practices/references/techniques-serialization.md +158 -0
- package/src/skills/nest-best-practices/references/techniques-sessions-cookies.md +167 -0
- package/src/skills/nest-best-practices/references/techniques-task-scheduling.md +166 -0
- package/src/skills/nest-best-practices/references/techniques-validation.md +126 -0
- package/src/skills/nest-best-practices/references/techniques-versioning.md +153 -0
- package/src/skills/nest-best-practices/references/websockets-advanced.md +96 -0
- package/src/skills/nest-best-practices/references/websockets-gateways.md +215 -0
- package/src/skills/tailwindcss-best-practices/SKILL.md +180 -0
- package/src/skills/tailwindcss-best-practices/references/best-practices-utility-patterns.md +87 -0
- package/src/skills/tailwindcss-best-practices/references/core-installation.md +109 -0
- package/src/skills/tailwindcss-best-practices/references/core-preflight.md +200 -0
- package/src/skills/tailwindcss-best-practices/references/core-responsive.md +163 -0
- package/src/skills/tailwindcss-best-practices/references/core-source-detection.md +114 -0
- package/src/skills/tailwindcss-best-practices/references/core-theme.md +108 -0
- package/src/skills/tailwindcss-best-practices/references/core-utility-classes.md +59 -0
- package/src/skills/tailwindcss-best-practices/references/core-variants.md +204 -0
- package/src/skills/tailwindcss-best-practices/references/effects-form-controls.md +76 -0
- package/src/skills/tailwindcss-best-practices/references/effects-mask.md +91 -0
- package/src/skills/tailwindcss-best-practices/references/effects-scroll-snap.md +59 -0
- package/src/skills/tailwindcss-best-practices/references/effects-text-shadow.md +78 -0
- package/src/skills/tailwindcss-best-practices/references/effects-transition-animation.md +80 -0
- package/src/skills/tailwindcss-best-practices/references/effects-visibility-interactivity.md +82 -0
- package/src/skills/tailwindcss-best-practices/references/features-content-detection.md +175 -0
- package/src/skills/tailwindcss-best-practices/references/features-custom-styles.md +203 -0
- package/src/skills/tailwindcss-best-practices/references/features-dark-mode.md +137 -0
- package/src/skills/tailwindcss-best-practices/references/features-functions-directives.md +241 -0
- package/src/skills/tailwindcss-best-practices/references/features-upgrade.md +160 -0
- package/src/skills/tailwindcss-best-practices/references/layout-aspect-ratio.md +39 -0
- package/src/skills/tailwindcss-best-practices/references/layout-columns.md +80 -0
- package/src/skills/tailwindcss-best-practices/references/layout-display.md +110 -0
- package/src/skills/tailwindcss-best-practices/references/layout-flexbox.md +112 -0
- package/src/skills/tailwindcss-best-practices/references/layout-grid.md +87 -0
- package/src/skills/tailwindcss-best-practices/references/layout-height.md +97 -0
- package/src/skills/tailwindcss-best-practices/references/layout-inset.md +103 -0
- package/src/skills/tailwindcss-best-practices/references/layout-logical-properties.md +92 -0
- package/src/skills/tailwindcss-best-practices/references/layout-margin.md +126 -0
- package/src/skills/tailwindcss-best-practices/references/layout-min-max-sizing.md +63 -0
- package/src/skills/tailwindcss-best-practices/references/layout-object-fit-position.md +64 -0
- package/src/skills/tailwindcss-best-practices/references/layout-overflow.md +57 -0
- package/src/skills/tailwindcss-best-practices/references/layout-padding.md +77 -0
- package/src/skills/tailwindcss-best-practices/references/layout-position.md +85 -0
- package/src/skills/tailwindcss-best-practices/references/layout-tables.md +67 -0
- package/src/skills/tailwindcss-best-practices/references/layout-width.md +102 -0
- package/src/skills/tailwindcss-best-practices/references/transform-base.md +68 -0
- package/src/skills/tailwindcss-best-practices/references/transform-rotate.md +70 -0
- package/src/skills/tailwindcss-best-practices/references/transform-scale.md +83 -0
- package/src/skills/tailwindcss-best-practices/references/transform-skew.md +62 -0
- package/src/skills/tailwindcss-best-practices/references/transform-translate.md +77 -0
- package/src/skills/tailwindcss-best-practices/references/typography-font-text.md +142 -0
- package/src/skills/tailwindcss-best-practices/references/typography-list-style.md +65 -0
- package/src/skills/tailwindcss-best-practices/references/typography-text-align.md +60 -0
- package/src/skills/tailwindcss-best-practices/references/visual-background.md +76 -0
- package/src/skills/tailwindcss-best-practices/references/visual-border.md +108 -0
- package/src/skills/tailwindcss-best-practices/references/visual-effects.md +111 -0
- package/src/skills/tailwindcss-best-practices/references/visual-svg.md +82 -0
- package/src/skills/test-mobile-app/SKILL.md +11 -6
- package/src/skills/test-mobile-app/scripts/analyze_apk.py +15 -4
- package/src/skills/test-mobile-app/scripts/check_environment.py +5 -5
- package/src/skills/test-mobile-app/scripts/run_tests.py +1 -1
- package/src/skills/test-web-ui/SKILL.md +264 -84
- package/src/skills/test-web-ui/scripts/discover.py +25 -12
- package/src/skills/test-web-ui/scripts/run_tests.py +3 -2
- package/src/skills/typescript-expert/SKILL.md +145 -0
- package/src/skills/typescript-expert/commands/typescript-fix.md +65 -0
- package/src/skills/typescript-expert/references/advanced-conditional-types.md +190 -0
- package/src/skills/typescript-expert/references/advanced-decorators.md +243 -0
- package/src/skills/typescript-expert/references/advanced-mapped-types.md +223 -0
- package/src/skills/typescript-expert/references/advanced-template-literals.md +209 -0
- package/src/skills/typescript-expert/references/advanced-type-guards.md +308 -0
- package/src/skills/typescript-expert/references/best-practices-patterns.md +313 -0
- package/src/skills/typescript-expert/references/best-practices-performance.md +185 -0
- package/src/skills/typescript-expert/references/best-practices-tsconfig.md +242 -0
- package/src/skills/typescript-expert/references/core-generics.md +246 -0
- package/src/skills/typescript-expert/references/core-interfaces-types.md +231 -0
- package/src/skills/typescript-expert/references/core-type-system.md +261 -0
- package/src/skills/typescript-expert/references/core-utility-types.md +235 -0
- package/src/skills/typescript-expert/references/features-ts5x.md +370 -0
- package/src/skills/vite-best-practices/SKILL.md +115 -0
- package/src/skills/vite-best-practices/references/build-and-ssr.md +255 -0
- package/src/skills/vite-best-practices/references/core-config.md +231 -0
- package/src/skills/vite-best-practices/references/core-features.md +222 -0
- package/src/skills/vite-best-practices/references/core-plugin-api.md +294 -0
- package/src/skills/vite-best-practices/references/environment-api.md +108 -0
- package/src/skills/vite-best-practices/references/rolldown-migration.md +242 -0
- package/codex-cli-workspace/iteration-1/benchmark.json +0 -122
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/eval_metadata.json +0 -13
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/with_skill/grading.json +0 -52
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/with_skill/outputs/response.md +0 -163
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/with_skill/timing.json +0 -5
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/without_skill/grading.json +0 -58
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/without_skill/outputs/response.md +0 -151
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/without_skill/timing.json +0 -5
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/eval_metadata.json +0 -13
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/grading.json +0 -52
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/outputs/response.md +0 -86
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/timing.json +0 -5
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/grading.json +0 -58
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/outputs/response.md +0 -164
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/timing.json +0 -5
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/eval_metadata.json +0 -13
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/with_skill/grading.json +0 -52
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/with_skill/outputs/response.md +0 -130
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/with_skill/timing.json +0 -5
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/without_skill/grading.json +0 -64
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/without_skill/outputs/response.md +0 -209
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/without_skill/timing.json +0 -5
- package/codex-cli-workspace/iteration-1/review.html +0 -1325
- package/gemini-cli-workspace/iteration-1/benchmark.json +0 -86
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/eval_metadata.json +0 -37
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/with_skill/grading.json +0 -37
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/with_skill/outputs/response.md +0 -401
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/with_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/without_skill/grading.json +0 -37
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/without_skill/outputs/response.md +0 -405
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/without_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/eval_metadata.json +0 -37
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/grading.json +0 -37
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/outputs/response.md +0 -212
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/grading.json +0 -37
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/outputs/response.md +0 -427
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/eval_metadata.json +0 -32
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/with_skill/grading.json +0 -32
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/with_skill/outputs/response.md +0 -171
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/with_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/without_skill/grading.json +0 -32
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/without_skill/outputs/response.md +0 -199
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/without_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-1/review.html +0 -1325
- package/gemini-cli-workspace/iteration-2/benchmark.json +0 -173
- package/gemini-cli-workspace/iteration-2/benchmark.md +0 -28
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/eval_metadata.json +0 -37
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/with_skill/grading.json +0 -37
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/with_skill/outputs/response.md +0 -195
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/with_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/without_skill/grading.json +0 -37
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/without_skill/outputs/response.md +0 -377
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/without_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/eval_metadata.json +0 -37
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/with_skill/grading.json +0 -37
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/with_skill/outputs/response.md +0 -127
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/with_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/without_skill/grading.json +0 -37
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/without_skill/outputs/response.md +0 -164
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/without_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/eval_metadata.json +0 -32
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/with_skill/grading.json +0 -32
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/with_skill/outputs/response.md +0 -91
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/with_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/without_skill/grading.json +0 -32
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/without_skill/outputs/response.md +0 -112
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/without_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-2/eval-viewer.html +0 -1325
- package/screen-recording-workspace/evals.json +0 -41
- package/screen-recording-workspace/iteration-1/benchmark.json +0 -102
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/eval_metadata.json +0 -31
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/with_skill/grading.json +0 -11
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/with_skill/outputs/demo.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/with_skill/timing.json +0 -5
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/without_skill/grading.json +0 -11
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/without_skill/outputs/demo.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/without_skill/timing.json +0 -5
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/eval_metadata.json +0 -31
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/with_skill/grading.json +0 -11
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/with_skill/outputs/region_capture.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/with_skill/timing.json +0 -5
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/without_skill/grading.json +0 -11
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/without_skill/outputs/region_capture.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/without_skill/timing.json +0 -5
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/eval_metadata.json +0 -31
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/with_skill/grading.json +0 -11
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/with_skill/outputs/fallback_recording.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/with_skill/timing.json +0 -5
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/without_skill/grading.json +0 -11
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/without_skill/outputs/fallback_recording.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/without_skill/outputs/record_screen.py +0 -67
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/without_skill/timing.json +0 -5
- package/screen-recording-workspace/iteration-1/review.html +0 -1325
- package/src/skills/codex-cli/evals/evals.json +0 -47
- package/src/skills/gemini-cli/evals/evals.json +0 -46
- package/src/skills/tm-search/evals/evals.json +0 -23
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mvc-serve-static
|
|
3
|
+
description: MVC template rendering and serving static files/SPA
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# MVC and Serve Static
|
|
7
|
+
|
|
8
|
+
## MVC (Template Rendering)
|
|
9
|
+
|
|
10
|
+
### Express Setup
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install hbs
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { NestFactory } from '@nestjs/core';
|
|
18
|
+
import { NestExpressApplication } from '@nestjs/platform-express';
|
|
19
|
+
import { join } from 'node:path';
|
|
20
|
+
import { AppModule } from './app.module';
|
|
21
|
+
|
|
22
|
+
async function bootstrap() {
|
|
23
|
+
const app = await NestFactory.create<NestExpressApplication>(AppModule);
|
|
24
|
+
app.useStaticAssets(join(__dirname, '..', 'public'));
|
|
25
|
+
app.setBaseViewsDir(join(__dirname, '..', 'views'));
|
|
26
|
+
app.setViewEngine('hbs');
|
|
27
|
+
await app.listen(3000);
|
|
28
|
+
}
|
|
29
|
+
bootstrap();
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Controller with @Render
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { Get, Controller, Render } from '@nestjs/common';
|
|
36
|
+
|
|
37
|
+
@Controller()
|
|
38
|
+
export class AppController {
|
|
39
|
+
@Get()
|
|
40
|
+
@Render('index')
|
|
41
|
+
root() {
|
|
42
|
+
return { message: 'Hello world!' };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Dynamic Template Selection
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { Get, Controller, Res } from '@nestjs/common';
|
|
51
|
+
import { Response } from 'express';
|
|
52
|
+
|
|
53
|
+
@Controller()
|
|
54
|
+
export class AppController {
|
|
55
|
+
@Get()
|
|
56
|
+
root(@Res() res: Response) {
|
|
57
|
+
return res.render('dynamic-view', { message: 'Hello!' });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Fastify
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm install @fastify/static @fastify/view handlebars
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
const app = await NestFactory.create<NestFastifyApplication>(
|
|
70
|
+
AppModule,
|
|
71
|
+
new FastifyAdapter(),
|
|
72
|
+
);
|
|
73
|
+
app.useStaticAssets({
|
|
74
|
+
root: join(__dirname, '..', 'public'),
|
|
75
|
+
prefix: '/public/',
|
|
76
|
+
});
|
|
77
|
+
app.setViewEngine({
|
|
78
|
+
engine: { handlebars: require('handlebars') },
|
|
79
|
+
templates: join(__dirname, '..', 'views'),
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
With Fastify, include file extension in `@Render()`: `@Render('index.hbs')`
|
|
84
|
+
|
|
85
|
+
## Serve Static (SPA)
|
|
86
|
+
|
|
87
|
+
Serve static content like Single Page Applications.
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npm install @nestjs/serve-static
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { Module } from '@nestjs/common';
|
|
95
|
+
import { ServeStaticModule } from '@nestjs/serve-static';
|
|
96
|
+
import { join } from 'path';
|
|
97
|
+
|
|
98
|
+
@Module({
|
|
99
|
+
imports: [
|
|
100
|
+
ServeStaticModule.forRoot({
|
|
101
|
+
rootPath: join(__dirname, '..', 'client'),
|
|
102
|
+
}),
|
|
103
|
+
],
|
|
104
|
+
})
|
|
105
|
+
export class AppModule {}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### SPA Client-Side Routing
|
|
109
|
+
|
|
110
|
+
Default `renderPath` is `*` (all paths). The module sends `index.html` for non-matching routes, enabling client-side routing. Controller paths take precedence.
|
|
111
|
+
|
|
112
|
+
### Configuration Options
|
|
113
|
+
|
|
114
|
+
| Option | Description |
|
|
115
|
+
|--------|-------------|
|
|
116
|
+
| `rootPath` | Path to static files |
|
|
117
|
+
| `serveRoot` | URL path prefix |
|
|
118
|
+
| `renderPath` | Paths to serve index.html |
|
|
119
|
+
| `exclude` | Excluded paths |
|
|
120
|
+
|
|
121
|
+
## Key Points
|
|
122
|
+
|
|
123
|
+
- Use `NestExpressApplication` or `NestFastifyApplication` for MVC
|
|
124
|
+
- `@Render()` passes return object to template as variables
|
|
125
|
+
- ServeStatic fallback enables SPA routing
|
|
126
|
+
- Fastify: set `serveStaticOptions.fallthrough: true` for SPA fallback
|
|
127
|
+
|
|
128
|
+
<!--
|
|
129
|
+
Source references:
|
|
130
|
+
- https://docs.nestjs.com/techniques/mvc
|
|
131
|
+
- https://docs.nestjs.com/recipes/serve-static
|
|
132
|
+
-->
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: queues
|
|
3
|
+
description: Background job processing with BullMQ and Bull
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Queues
|
|
7
|
+
|
|
8
|
+
Queues help with task scheduling, load balancing, and background processing using Redis-backed job queues.
|
|
9
|
+
|
|
10
|
+
## Installation (BullMQ - Recommended)
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @nestjs/bullmq bullmq
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Setup
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { Module } from '@nestjs/common';
|
|
20
|
+
import { BullModule } from '@nestjs/bullmq';
|
|
21
|
+
|
|
22
|
+
@Module({
|
|
23
|
+
imports: [
|
|
24
|
+
BullModule.forRoot({
|
|
25
|
+
connection: {
|
|
26
|
+
host: 'localhost',
|
|
27
|
+
port: 6379,
|
|
28
|
+
},
|
|
29
|
+
}),
|
|
30
|
+
BullModule.registerQueue({ name: 'audio' }),
|
|
31
|
+
],
|
|
32
|
+
})
|
|
33
|
+
export class AppModule {}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Producer (Adding Jobs)
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { Injectable } from '@nestjs/common';
|
|
40
|
+
import { InjectQueue } from '@nestjs/bullmq';
|
|
41
|
+
import { Queue } from 'bullmq';
|
|
42
|
+
|
|
43
|
+
@Injectable()
|
|
44
|
+
export class AudioService {
|
|
45
|
+
constructor(@InjectQueue('audio') private audioQueue: Queue) {}
|
|
46
|
+
|
|
47
|
+
async addTranscodeJob(file: string) {
|
|
48
|
+
await this.audioQueue.add('transcode', { file });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// With options
|
|
52
|
+
async addDelayedJob(data: any) {
|
|
53
|
+
await this.audioQueue.add('process', data, {
|
|
54
|
+
delay: 5000, // 5 second delay
|
|
55
|
+
attempts: 3, // Retry 3 times
|
|
56
|
+
removeOnComplete: true,
|
|
57
|
+
priority: 1, // Higher priority
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Consumer (Processing Jobs)
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { Processor, WorkerHost, OnWorkerEvent } from '@nestjs/bullmq';
|
|
67
|
+
import { Job } from 'bullmq';
|
|
68
|
+
|
|
69
|
+
@Processor('audio')
|
|
70
|
+
export class AudioConsumer extends WorkerHost {
|
|
71
|
+
async process(job: Job<any, any, string>): Promise<any> {
|
|
72
|
+
switch (job.name) {
|
|
73
|
+
case 'transcode':
|
|
74
|
+
return this.transcode(job.data);
|
|
75
|
+
case 'compress':
|
|
76
|
+
return this.compress(job.data);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private async transcode(data: any) {
|
|
81
|
+
// Processing logic
|
|
82
|
+
await job.updateProgress(50);
|
|
83
|
+
return { processed: true };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@OnWorkerEvent('completed')
|
|
87
|
+
onCompleted(job: Job) {
|
|
88
|
+
console.log(`Job ${job.id} completed`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@OnWorkerEvent('failed')
|
|
92
|
+
onFailed(job: Job, error: Error) {
|
|
93
|
+
console.error(`Job ${job.id} failed:`, error.message);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Register consumer as provider:
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
@Module({
|
|
102
|
+
providers: [AudioConsumer],
|
|
103
|
+
})
|
|
104
|
+
export class AudioModule {}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Queue Events Listener
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { QueueEventsHost, QueueEventsListener, OnQueueEvent } from '@nestjs/bullmq';
|
|
111
|
+
|
|
112
|
+
@QueueEventsListener('audio')
|
|
113
|
+
export class AudioEventsListener extends QueueEventsHost {
|
|
114
|
+
@OnQueueEvent('active')
|
|
115
|
+
onActive(job: { jobId: string }) {
|
|
116
|
+
console.log(`Processing job ${job.jobId}...`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Job Options
|
|
122
|
+
|
|
123
|
+
| Option | Description |
|
|
124
|
+
|--------|-------------|
|
|
125
|
+
| `delay` | Milliseconds to wait before processing |
|
|
126
|
+
| `attempts` | Number of retry attempts |
|
|
127
|
+
| `backoff` | Retry delay strategy |
|
|
128
|
+
| `priority` | Job priority (1 = highest) |
|
|
129
|
+
| `lifo` | Process as LIFO instead of FIFO |
|
|
130
|
+
| `removeOnComplete` | Remove job data after completion |
|
|
131
|
+
| `removeOnFail` | Remove job data after failure |
|
|
132
|
+
| `repeat` | Cron-like repeat configuration |
|
|
133
|
+
|
|
134
|
+
## Queue Management
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
await this.audioQueue.pause();
|
|
138
|
+
await this.audioQueue.resume();
|
|
139
|
+
await this.audioQueue.clean(1000); // Remove completed jobs older than 1s
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Request-Scoped Consumers
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
@Processor({ name: 'audio', scope: Scope.REQUEST })
|
|
146
|
+
export class AudioConsumer extends WorkerHost {
|
|
147
|
+
constructor(@Inject(JOB_REF) private jobRef: Job) {}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Key Points
|
|
152
|
+
|
|
153
|
+
- Consumers must be registered as providers
|
|
154
|
+
- BullMQ is recommended over Bull (actively developed)
|
|
155
|
+
- Use `switch` statement in `process()` for different job names
|
|
156
|
+
- Requires Redis for job persistence
|
|
157
|
+
- Jobs persist across restarts
|
|
158
|
+
|
|
159
|
+
<!--
|
|
160
|
+
Source references:
|
|
161
|
+
- https://docs.nestjs.com/techniques/queues
|
|
162
|
+
-->
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: serialization
|
|
3
|
+
description: Response serialization with class-transformer
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Serialization
|
|
7
|
+
|
|
8
|
+
Serialization transforms objects before sending responses, using `class-transformer` decorators.
|
|
9
|
+
|
|
10
|
+
## Basic Usage
|
|
11
|
+
|
|
12
|
+
Use `ClassSerializerInterceptor` to automatically transform responses:
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
import { Controller, Get, UseInterceptors } from '@nestjs/common';
|
|
16
|
+
import { ClassSerializerInterceptor } from '@nestjs/common';
|
|
17
|
+
|
|
18
|
+
@Controller('users')
|
|
19
|
+
@UseInterceptors(ClassSerializerInterceptor)
|
|
20
|
+
export class UsersController {
|
|
21
|
+
@Get(':id')
|
|
22
|
+
findOne() {
|
|
23
|
+
return new UserEntity({
|
|
24
|
+
id: 1,
|
|
25
|
+
firstName: 'John',
|
|
26
|
+
lastName: 'Doe',
|
|
27
|
+
password: 'secret123',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Exclude Properties
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { Exclude } from 'class-transformer';
|
|
37
|
+
|
|
38
|
+
export class UserEntity {
|
|
39
|
+
id: number;
|
|
40
|
+
firstName: string;
|
|
41
|
+
lastName: string;
|
|
42
|
+
|
|
43
|
+
@Exclude()
|
|
44
|
+
password: string;
|
|
45
|
+
|
|
46
|
+
constructor(partial: Partial<UserEntity>) {
|
|
47
|
+
Object.assign(this, partial);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Response excludes `password`:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{ "id": 1, "firstName": "John", "lastName": "Doe" }
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Expose Computed Properties
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { Expose } from 'class-transformer';
|
|
62
|
+
|
|
63
|
+
export class UserEntity {
|
|
64
|
+
firstName: string;
|
|
65
|
+
lastName: string;
|
|
66
|
+
|
|
67
|
+
@Expose()
|
|
68
|
+
get fullName(): string {
|
|
69
|
+
return `${this.firstName} ${this.lastName}`;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Transform Properties
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { Transform } from 'class-transformer';
|
|
78
|
+
|
|
79
|
+
export class UserEntity {
|
|
80
|
+
@Transform(({ value }) => value.name)
|
|
81
|
+
role: RoleEntity; // Outputs role.name instead of full object
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Serialization Options
|
|
86
|
+
|
|
87
|
+
Per-route options:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { SerializeOptions } from '@nestjs/common';
|
|
91
|
+
|
|
92
|
+
@Get()
|
|
93
|
+
@SerializeOptions({ excludePrefixes: ['_'] })
|
|
94
|
+
findAll() {
|
|
95
|
+
return this.usersService.findAll();
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Transform Plain Objects
|
|
100
|
+
|
|
101
|
+
Force transformation of plain objects:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
@Get()
|
|
105
|
+
@UseInterceptors(ClassSerializerInterceptor)
|
|
106
|
+
@SerializeOptions({ type: UserEntity })
|
|
107
|
+
findOne() {
|
|
108
|
+
return {
|
|
109
|
+
id: 1,
|
|
110
|
+
firstName: 'John',
|
|
111
|
+
password: 'secret', // Will be excluded
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Global Interceptor
|
|
117
|
+
|
|
118
|
+
Apply globally:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
@Module({
|
|
122
|
+
providers: [
|
|
123
|
+
{ provide: APP_INTERCEPTOR, useClass: ClassSerializerInterceptor },
|
|
124
|
+
],
|
|
125
|
+
})
|
|
126
|
+
export class AppModule {}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Groups
|
|
130
|
+
|
|
131
|
+
Expose different fields based on groups:
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
export class UserEntity {
|
|
135
|
+
@Expose({ groups: ['admin'] })
|
|
136
|
+
email: string;
|
|
137
|
+
|
|
138
|
+
@Expose({ groups: ['admin', 'user'] })
|
|
139
|
+
firstName: string;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Controller
|
|
143
|
+
@SerializeOptions({ groups: ['admin'] })
|
|
144
|
+
@Get('admin')
|
|
145
|
+
findForAdmin() {}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Key Points
|
|
149
|
+
|
|
150
|
+
- Must return class instances, not plain objects
|
|
151
|
+
- Works with WebSockets and Microservices
|
|
152
|
+
- `@Exclude()` and `@Expose()` from `class-transformer`
|
|
153
|
+
- Use `excludeExtraneousValues: true` to only include `@Expose()` fields
|
|
154
|
+
|
|
155
|
+
<!--
|
|
156
|
+
Source references:
|
|
157
|
+
- https://docs.nestjs.com/techniques/serialization
|
|
158
|
+
-->
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sessions-cookies
|
|
3
|
+
description: HTTP sessions and cookies for stateful applications
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Sessions and Cookies
|
|
7
|
+
|
|
8
|
+
## Sessions
|
|
9
|
+
|
|
10
|
+
### Express (Default)
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install express-session
|
|
14
|
+
npm install -D @types/express-session
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import * as session from 'express-session';
|
|
19
|
+
|
|
20
|
+
// main.ts
|
|
21
|
+
app.use(
|
|
22
|
+
session({
|
|
23
|
+
secret: 'my-secret',
|
|
24
|
+
resave: false,
|
|
25
|
+
saveUninitialized: false,
|
|
26
|
+
}),
|
|
27
|
+
);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Usage in controllers:
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
@Get()
|
|
34
|
+
findAll(@Req() request: Request) {
|
|
35
|
+
request.session.visits = (request.session.visits ?? 0) + 1;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Or using @Session decorator
|
|
39
|
+
@Get()
|
|
40
|
+
findAll(@Session() session: Record<string, any>) {
|
|
41
|
+
session.visits = (session.visits ?? 0) + 1;
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Fastify
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install @fastify/secure-session
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import secureSession from '@fastify/secure-session';
|
|
53
|
+
|
|
54
|
+
const app = await NestFactory.create<NestFastifyApplication>(
|
|
55
|
+
AppModule,
|
|
56
|
+
new FastifyAdapter(),
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
await app.register(secureSession, {
|
|
60
|
+
secret: 'averylogphrasebiggerthanthirtytwochars',
|
|
61
|
+
salt: 'mq9hDxBVDbspDR6n',
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
@Get()
|
|
67
|
+
findAll(@Req() request: FastifyRequest) {
|
|
68
|
+
const visits = request.session.get('visits') ?? 0;
|
|
69
|
+
request.session.set('visits', visits + 1);
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Cookies
|
|
74
|
+
|
|
75
|
+
### Express (Default)
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npm install cookie-parser
|
|
79
|
+
npm install -D @types/cookie-parser
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import * as cookieParser from 'cookie-parser';
|
|
84
|
+
|
|
85
|
+
app.use(cookieParser());
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Reading and setting cookies:
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
@Get()
|
|
92
|
+
getCookies(@Req() request: Request) {
|
|
93
|
+
console.log(request.cookies);
|
|
94
|
+
console.log(request.signedCookies);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@Get()
|
|
98
|
+
setCookie(@Res({ passthrough: true }) response: Response) {
|
|
99
|
+
response.cookie('key', 'value', {
|
|
100
|
+
httpOnly: true,
|
|
101
|
+
secure: true,
|
|
102
|
+
maxAge: 1000 * 60 * 60 * 24, // 1 day
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Fastify
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
npm install @fastify/cookie
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
import fastifyCookie from '@fastify/cookie';
|
|
115
|
+
|
|
116
|
+
await app.register(fastifyCookie, {
|
|
117
|
+
secret: 'my-secret',
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
@Get()
|
|
123
|
+
setCookie(@Res({ passthrough: true }) response: FastifyReply) {
|
|
124
|
+
response.setCookie('key', 'value');
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Custom Cookie Decorator
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
|
|
132
|
+
|
|
133
|
+
export const Cookies = createParamDecorator(
|
|
134
|
+
(data: string, ctx: ExecutionContext) => {
|
|
135
|
+
const request = ctx.switchToHttp().getRequest();
|
|
136
|
+
return data ? request.cookies?.[data] : request.cookies;
|
|
137
|
+
},
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
// Usage
|
|
141
|
+
@Get()
|
|
142
|
+
findAll(@Cookies('name') name: string) {}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Session Configuration Options
|
|
146
|
+
|
|
147
|
+
| Option | Description |
|
|
148
|
+
|--------|-------------|
|
|
149
|
+
| `secret` | Used to sign session ID cookie |
|
|
150
|
+
| `resave` | Force save even if unmodified (set to `false`) |
|
|
151
|
+
| `saveUninitialized` | Save uninitialized sessions (set to `false` for login flows) |
|
|
152
|
+
| `cookie.secure` | Require HTTPS (recommended for production) |
|
|
153
|
+
| `cookie.httpOnly` | Prevent client-side access |
|
|
154
|
+
|
|
155
|
+
## Key Points
|
|
156
|
+
|
|
157
|
+
- Default session storage is not for production (leaks memory)
|
|
158
|
+
- Use Redis or database-backed session store in production
|
|
159
|
+
- Set `secure: true` for production cookies
|
|
160
|
+
- Use `passthrough: true` with `@Res()` to keep NestJS response handling
|
|
161
|
+
- Session decorator is `@Session()` from `@nestjs/common`
|
|
162
|
+
|
|
163
|
+
<!--
|
|
164
|
+
Source references:
|
|
165
|
+
- https://docs.nestjs.com/techniques/session
|
|
166
|
+
- https://docs.nestjs.com/techniques/cookies
|
|
167
|
+
-->
|