@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,233 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: graphql
|
|
3
|
+
description: Building GraphQL APIs with code-first and schema-first approaches
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GraphQL
|
|
7
|
+
|
|
8
|
+
NestJS provides GraphQL integration through Apollo Server or Mercurius.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# Apollo (default)
|
|
14
|
+
npm install @nestjs/graphql @nestjs/apollo @apollo/server @as-integrations/express5 graphql
|
|
15
|
+
|
|
16
|
+
# Mercurius (Fastify)
|
|
17
|
+
npm install @nestjs/graphql @nestjs/mercurius graphql mercurius
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Setup
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { Module } from '@nestjs/common';
|
|
24
|
+
import { GraphQLModule } from '@nestjs/graphql';
|
|
25
|
+
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
|
|
26
|
+
import { join } from 'path';
|
|
27
|
+
|
|
28
|
+
@Module({
|
|
29
|
+
imports: [
|
|
30
|
+
GraphQLModule.forRoot<ApolloDriverConfig>({
|
|
31
|
+
driver: ApolloDriver,
|
|
32
|
+
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
|
|
33
|
+
// Or in-memory: autoSchemaFile: true
|
|
34
|
+
}),
|
|
35
|
+
],
|
|
36
|
+
})
|
|
37
|
+
export class AppModule {}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Code-First Approach
|
|
41
|
+
|
|
42
|
+
### Object Type
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { ObjectType, Field, ID, Int } from '@nestjs/graphql';
|
|
46
|
+
|
|
47
|
+
@ObjectType()
|
|
48
|
+
export class Author {
|
|
49
|
+
@Field(() => ID)
|
|
50
|
+
id: string;
|
|
51
|
+
|
|
52
|
+
@Field()
|
|
53
|
+
name: string;
|
|
54
|
+
|
|
55
|
+
@Field(() => Int, { nullable: true })
|
|
56
|
+
age?: number;
|
|
57
|
+
|
|
58
|
+
@Field(() => [Post])
|
|
59
|
+
posts: Post[];
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Resolver
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { Resolver, Query, Mutation, Args, ID } from '@nestjs/graphql';
|
|
67
|
+
|
|
68
|
+
@Resolver(() => Author)
|
|
69
|
+
export class AuthorsResolver {
|
|
70
|
+
constructor(private authorsService: AuthorsService) {}
|
|
71
|
+
|
|
72
|
+
@Query(() => [Author], { name: 'authors' })
|
|
73
|
+
findAll() {
|
|
74
|
+
return this.authorsService.findAll();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@Query(() => Author, { name: 'author' })
|
|
78
|
+
findOne(@Args('id', { type: () => ID }) id: string) {
|
|
79
|
+
return this.authorsService.findOne(id);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@Mutation(() => Author)
|
|
83
|
+
createAuthor(@Args('input') input: CreateAuthorInput) {
|
|
84
|
+
return this.authorsService.create(input);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Input Type
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { InputType, Field } from '@nestjs/graphql';
|
|
93
|
+
|
|
94
|
+
@InputType()
|
|
95
|
+
export class CreateAuthorInput {
|
|
96
|
+
@Field()
|
|
97
|
+
name: string;
|
|
98
|
+
|
|
99
|
+
@Field({ nullable: true })
|
|
100
|
+
bio?: string;
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Schema-First Approach
|
|
105
|
+
|
|
106
|
+
### GraphQL Schema
|
|
107
|
+
|
|
108
|
+
```graphql
|
|
109
|
+
# authors.graphql
|
|
110
|
+
type Author {
|
|
111
|
+
id: ID!
|
|
112
|
+
name: String!
|
|
113
|
+
posts: [Post!]!
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
type Query {
|
|
117
|
+
authors: [Author!]!
|
|
118
|
+
author(id: ID!): Author
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Configuration
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
GraphQLModule.forRoot<ApolloDriverConfig>({
|
|
126
|
+
driver: ApolloDriver,
|
|
127
|
+
typePaths: ['./**/*.graphql'],
|
|
128
|
+
definitions: {
|
|
129
|
+
path: join(process.cwd(), 'src/graphql.ts'),
|
|
130
|
+
outputAs: 'class',
|
|
131
|
+
},
|
|
132
|
+
}),
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Resolver
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
@Resolver('Author')
|
|
139
|
+
export class AuthorsResolver {
|
|
140
|
+
@Query('authors')
|
|
141
|
+
findAll() {
|
|
142
|
+
return this.authorsService.findAll();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
@Query('author')
|
|
146
|
+
findOne(@Args('id') id: string) {
|
|
147
|
+
return this.authorsService.findOne(id);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Subscriptions
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
import { Subscription, Resolver } from '@nestjs/graphql';
|
|
156
|
+
import { PubSub } from 'graphql-subscriptions';
|
|
157
|
+
|
|
158
|
+
const pubSub = new PubSub();
|
|
159
|
+
|
|
160
|
+
@Resolver()
|
|
161
|
+
export class AuthorsResolver {
|
|
162
|
+
@Mutation(() => Author)
|
|
163
|
+
async createAuthor(@Args('input') input: CreateAuthorInput) {
|
|
164
|
+
const author = await this.authorsService.create(input);
|
|
165
|
+
pubSub.publish('authorCreated', { authorCreated: author });
|
|
166
|
+
return author;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
@Subscription(() => Author)
|
|
170
|
+
authorCreated() {
|
|
171
|
+
return pubSub.asyncIterableIterator('authorCreated');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Field Resolvers
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
@Resolver(() => Author)
|
|
180
|
+
export class AuthorsResolver {
|
|
181
|
+
@ResolveField(() => [Post])
|
|
182
|
+
posts(@Parent() author: Author) {
|
|
183
|
+
return this.postsService.findByAuthorId(author.id);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Guards and Interceptors
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
@Query(() => Author)
|
|
192
|
+
@UseGuards(GqlAuthGuard)
|
|
193
|
+
whoAmI(@CurrentUser() user: User) {
|
|
194
|
+
return user;
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Context
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
GraphQLModule.forRoot<ApolloDriverConfig>({
|
|
202
|
+
driver: ApolloDriver,
|
|
203
|
+
autoSchemaFile: true,
|
|
204
|
+
context: ({ req, res }) => ({ req, res }),
|
|
205
|
+
}),
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Async Configuration
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
GraphQLModule.forRootAsync<ApolloDriverConfig>({
|
|
212
|
+
driver: ApolloDriver,
|
|
213
|
+
imports: [ConfigModule],
|
|
214
|
+
useFactory: async (configService: ConfigService) => ({
|
|
215
|
+
autoSchemaFile: true,
|
|
216
|
+
playground: configService.get('NODE_ENV') !== 'production',
|
|
217
|
+
}),
|
|
218
|
+
inject: [ConfigService],
|
|
219
|
+
}),
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Key Points
|
|
223
|
+
|
|
224
|
+
- **Code-first**: TypeScript classes generate GraphQL schema
|
|
225
|
+
- **Schema-first**: SDL files generate TypeScript types
|
|
226
|
+
- Use `autoSchemaFile` for code-first
|
|
227
|
+
- Use `typePaths` for schema-first
|
|
228
|
+
- Resolvers must be registered as providers
|
|
229
|
+
|
|
230
|
+
<!--
|
|
231
|
+
Source references:
|
|
232
|
+
- https://docs.nestjs.com/graphql/quick-start
|
|
233
|
+
-->
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: graphql-resolvers-mutations
|
|
3
|
+
description: GraphQL resolvers, mutations, and field resolvers
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GraphQL Resolvers & Mutations
|
|
7
|
+
|
|
8
|
+
## Object Types (Code First)
|
|
9
|
+
|
|
10
|
+
```typescript
|
|
11
|
+
import { ObjectType, Field, ID, Int } from '@nestjs/graphql';
|
|
12
|
+
|
|
13
|
+
@ObjectType()
|
|
14
|
+
export class Author {
|
|
15
|
+
@Field(() => ID)
|
|
16
|
+
id: string;
|
|
17
|
+
|
|
18
|
+
@Field()
|
|
19
|
+
name: string;
|
|
20
|
+
|
|
21
|
+
@Field(() => Int, { nullable: true })
|
|
22
|
+
age?: number;
|
|
23
|
+
|
|
24
|
+
@Field(() => [Post])
|
|
25
|
+
posts: Post[];
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Resolver
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { Resolver, Query, Mutation, Args, ResolveField, Parent, ID } from '@nestjs/graphql';
|
|
33
|
+
|
|
34
|
+
@Resolver(() => Author)
|
|
35
|
+
export class AuthorsResolver {
|
|
36
|
+
constructor(
|
|
37
|
+
private authorsService: AuthorsService,
|
|
38
|
+
private postsService: PostsService,
|
|
39
|
+
) {}
|
|
40
|
+
|
|
41
|
+
@Query(() => [Author], { name: 'authors' })
|
|
42
|
+
findAll() {
|
|
43
|
+
return this.authorsService.findAll();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@Query(() => Author, { nullable: true })
|
|
47
|
+
findOne(@Args('id', { type: () => ID }) id: string) {
|
|
48
|
+
return this.authorsService.findOne(id);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@ResolveField(() => [Post])
|
|
52
|
+
posts(@Parent() author: Author) {
|
|
53
|
+
return this.postsService.findByAuthorId(author.id);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Mutations
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { InputType, Field, ArgsType } from '@nestjs/graphql';
|
|
62
|
+
|
|
63
|
+
@InputType()
|
|
64
|
+
export class CreateAuthorInput {
|
|
65
|
+
@Field()
|
|
66
|
+
name: string;
|
|
67
|
+
|
|
68
|
+
@Field({ nullable: true })
|
|
69
|
+
bio?: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@Resolver(() => Author)
|
|
73
|
+
export class AuthorsResolver {
|
|
74
|
+
@Mutation(() => Author)
|
|
75
|
+
createAuthor(@Args('input') input: CreateAuthorInput) {
|
|
76
|
+
return this.authorsService.create(input);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@Mutation(() => Author)
|
|
80
|
+
updateAuthor(
|
|
81
|
+
@Args('id', { type: () => ID }) id: string,
|
|
82
|
+
@Args('input') input: UpdateAuthorInput,
|
|
83
|
+
) {
|
|
84
|
+
return this.authorsService.update(id, input);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@Mutation(() => Boolean)
|
|
88
|
+
deleteAuthor(@Args('id', { type: () => ID }) id: string) {
|
|
89
|
+
return this.authorsService.delete(id);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Args Class
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
@ArgsType()
|
|
98
|
+
class GetAuthorsArgs {
|
|
99
|
+
@Field(() => Int, { defaultValue: 0 })
|
|
100
|
+
offset: number;
|
|
101
|
+
|
|
102
|
+
@Field(() => Int, { defaultValue: 10 })
|
|
103
|
+
limit: number;
|
|
104
|
+
|
|
105
|
+
@Field({ nullable: true })
|
|
106
|
+
search?: string;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@Query(() => [Author])
|
|
110
|
+
authors(@Args() args: GetAuthorsArgs) {
|
|
111
|
+
return this.authorsService.findAll(args);
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Field Options
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
@Field(() => String, {
|
|
119
|
+
description: 'The author name',
|
|
120
|
+
deprecationReason: 'Use fullName instead',
|
|
121
|
+
nullable: true,
|
|
122
|
+
})
|
|
123
|
+
name?: string;
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Nullable Arrays
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
// Array itself is nullable
|
|
130
|
+
@Field(() => [Post], { nullable: true })
|
|
131
|
+
posts?: Post[];
|
|
132
|
+
|
|
133
|
+
// Array items are nullable
|
|
134
|
+
@Field(() => [Post], { nullable: 'items' })
|
|
135
|
+
posts: (Post | null)[];
|
|
136
|
+
|
|
137
|
+
// Both nullable
|
|
138
|
+
@Field(() => [Post], { nullable: 'itemsAndList' })
|
|
139
|
+
posts?: (Post | null)[];
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## GraphQL Decorators
|
|
143
|
+
|
|
144
|
+
| Decorator | Purpose |
|
|
145
|
+
|-----------|---------|
|
|
146
|
+
| `@ObjectType()` | Define GraphQL type |
|
|
147
|
+
| `@Field()` | Define field |
|
|
148
|
+
| `@InputType()` | Define input type |
|
|
149
|
+
| `@ArgsType()` | Define args class |
|
|
150
|
+
| `@Resolver()` | Define resolver |
|
|
151
|
+
| `@Query()` | Define query |
|
|
152
|
+
| `@Mutation()` | Define mutation |
|
|
153
|
+
| `@ResolveField()` | Define field resolver |
|
|
154
|
+
| `@Parent()` | Access parent object |
|
|
155
|
+
| `@Args()` | Access arguments |
|
|
156
|
+
| `@Context()` | Access context |
|
|
157
|
+
|
|
158
|
+
## Query Options
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
@Query(() => Author, {
|
|
162
|
+
name: 'author', // GraphQL query name
|
|
163
|
+
description: 'Get author by ID',
|
|
164
|
+
nullable: true, // Can return null
|
|
165
|
+
deprecationReason: 'Use findAuthor instead',
|
|
166
|
+
})
|
|
167
|
+
async getAuthor(@Args('id', { type: () => ID }) id: string) {}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Context Access
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
@Query(() => Author)
|
|
174
|
+
whoAmI(@Context() context: any) {
|
|
175
|
+
return context.req.user;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Or extract specific property
|
|
179
|
+
@Query(() => Author)
|
|
180
|
+
whoAmI(@Context('req') req: Request) {
|
|
181
|
+
return req.user;
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Using Guards
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
@Query(() => Author)
|
|
189
|
+
@UseGuards(GqlAuthGuard)
|
|
190
|
+
whoAmI(@Context() context: any) {
|
|
191
|
+
return context.req.user;
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
<!--
|
|
196
|
+
Source references:
|
|
197
|
+
- https://docs.nestjs.com/graphql/resolvers-map
|
|
198
|
+
- https://docs.nestjs.com/graphql/mutations
|
|
199
|
+
-->
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: graphql-scalars-unions-enums
|
|
3
|
+
description: GraphQL custom scalars, interfaces, union types, and enums
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GraphQL Scalars, Interfaces, Unions & Enums
|
|
7
|
+
|
|
8
|
+
## Interfaces
|
|
9
|
+
|
|
10
|
+
```typescript
|
|
11
|
+
import { Field, ID, InterfaceType } from '@nestjs/graphql';
|
|
12
|
+
|
|
13
|
+
@InterfaceType()
|
|
14
|
+
export abstract class Character {
|
|
15
|
+
@Field(() => ID)
|
|
16
|
+
id: string;
|
|
17
|
+
|
|
18
|
+
@Field()
|
|
19
|
+
name: string;
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Implement interface:
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
@ObjectType({ implements: () => [Character] })
|
|
27
|
+
export class Human implements Character {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Custom `resolveType`:
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
@InterfaceType({
|
|
37
|
+
resolveType(book) {
|
|
38
|
+
if (book.colors) return ColoringBook;
|
|
39
|
+
return TextBook;
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
export abstract class Book { ... }
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Interface resolver (shared field resolvers):
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
@Resolver(() => Character)
|
|
49
|
+
export class CharacterInterfaceResolver {
|
|
50
|
+
@ResolveField(() => [Character])
|
|
51
|
+
friends(@Parent() character) {
|
|
52
|
+
return this.getFriends(character);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Scalars, Unions & Enums
|
|
58
|
+
|
|
59
|
+
## Built-in Scalars
|
|
60
|
+
|
|
61
|
+
- `ID`, `Int`, `Float`, `String`, `Boolean`
|
|
62
|
+
- `GraphQLISODateTime` (default for Date)
|
|
63
|
+
- `GraphQLTimestamp` (Date as epoch ms)
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
GraphQLModule.forRoot({
|
|
67
|
+
buildSchemaOptions: {
|
|
68
|
+
dateScalarMode: 'timestamp', // Use GraphQLTimestamp for Date
|
|
69
|
+
numberScalarMode: 'integer', // Use Int for number
|
|
70
|
+
},
|
|
71
|
+
}),
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Custom Scalar
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { Scalar, CustomScalar } from '@nestjs/graphql';
|
|
78
|
+
import { Kind, ValueNode } from 'graphql';
|
|
79
|
+
|
|
80
|
+
@Scalar('Date', () => Date)
|
|
81
|
+
export class DateScalar implements CustomScalar<number, Date> {
|
|
82
|
+
description = 'Date custom scalar';
|
|
83
|
+
|
|
84
|
+
parseValue(value: number): Date {
|
|
85
|
+
return new Date(value);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
serialize(value: Date): number {
|
|
89
|
+
return value.getTime();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
parseLiteral(ast: ValueNode): Date {
|
|
93
|
+
if (ast.kind === Kind.INT) return new Date(ast.value);
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Register as provider. Use: `@Field(() => Date) creationDate: Date;`
|
|
100
|
+
|
|
101
|
+
## Import Scalar (e.g., JSON)
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npm i graphql-type-json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import GraphQLJSON from 'graphql-type-json';
|
|
109
|
+
|
|
110
|
+
GraphQLModule.forRoot({
|
|
111
|
+
resolvers: { JSON: GraphQLJSON },
|
|
112
|
+
}),
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Union Types
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import { createUnionType } from '@nestjs/graphql';
|
|
119
|
+
|
|
120
|
+
export const ResultUnion = createUnionType({
|
|
121
|
+
name: 'ResultUnion',
|
|
122
|
+
types: () => [Author, Book] as const,
|
|
123
|
+
resolveType(value) {
|
|
124
|
+
if (value.name) return Author;
|
|
125
|
+
if (value.title) return Book;
|
|
126
|
+
return null;
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
@Query(() => [ResultUnion])
|
|
131
|
+
search(): Array<typeof ResultUnion> {
|
|
132
|
+
return [new Author(), new Book()];
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Return class instances for default `resolveType`. Schema first: add `__resolveType` resolver.
|
|
137
|
+
|
|
138
|
+
## Enums
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
import { registerEnumType } from '@nestjs/graphql';
|
|
142
|
+
|
|
143
|
+
export enum AllowedColor {
|
|
144
|
+
RED,
|
|
145
|
+
GREEN,
|
|
146
|
+
BLUE,
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
registerEnumType(AllowedColor, {
|
|
150
|
+
name: 'AllowedColor',
|
|
151
|
+
description: 'Supported colors',
|
|
152
|
+
valuesMap: {
|
|
153
|
+
RED: { description: 'Default color' },
|
|
154
|
+
BLUE: { deprecationReason: 'Too blue' },
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
@Field(() => AllowedColor)
|
|
161
|
+
favoriteColor: AllowedColor;
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Schema first: define in SDL; use `resolvers` for internal value mapping.
|
|
165
|
+
|
|
166
|
+
## Key Points
|
|
167
|
+
|
|
168
|
+
- Use abstract class with `@InterfaceType()` (not TypeScript interface)
|
|
169
|
+
- `implements: () => [Character]` for ObjectType implementing interface
|
|
170
|
+
- Use `as const` for union types array
|
|
171
|
+
- Custom scalars need `parseValue`, `serialize`, `parseLiteral`
|
|
172
|
+
- `graphql-scalars` package for common scalars (UUID, Email, etc.)
|
|
173
|
+
- Enum internal values: use resolver object in schema-first
|
|
174
|
+
|
|
175
|
+
<!--
|
|
176
|
+
Source references:
|
|
177
|
+
- https://docs.nestjs.com/graphql/interfaces
|
|
178
|
+
- https://docs.nestjs.com/graphql/scalars
|
|
179
|
+
- https://docs.nestjs.com/graphql/unions-and-enums
|
|
180
|
+
-->
|