@biggora/claude-plugins 1.2.2 → 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.
Files changed (84) hide show
  1. package/README.md +2 -0
  2. package/package.json +1 -1
  3. package/registry/registry.json +15 -0
  4. package/specs/coding.md +6 -0
  5. package/src/commands/skills/add.js +63 -7
  6. package/src/commands/skills/list.js +23 -52
  7. package/src/commands/skills/remove.js +26 -27
  8. package/src/commands/skills/resolve.js +155 -0
  9. package/src/commands/skills/update.js +58 -74
  10. package/src/skills/nest-best-practices/SKILL.md +251 -0
  11. package/src/skills/nest-best-practices/references/best-practices-request-lifecycle.md +158 -0
  12. package/src/skills/nest-best-practices/references/cli-monorepo.md +106 -0
  13. package/src/skills/nest-best-practices/references/cli-overview.md +157 -0
  14. package/src/skills/nest-best-practices/references/core-controllers.md +165 -0
  15. package/src/skills/nest-best-practices/references/core-dependency-injection.md +179 -0
  16. package/src/skills/nest-best-practices/references/core-middleware.md +139 -0
  17. package/src/skills/nest-best-practices/references/core-modules.md +138 -0
  18. package/src/skills/nest-best-practices/references/core-providers.md +188 -0
  19. package/src/skills/nest-best-practices/references/faq-raw-body-hybrid.md +122 -0
  20. package/src/skills/nest-best-practices/references/fundamentals-circular-dependency.md +89 -0
  21. package/src/skills/nest-best-practices/references/fundamentals-custom-decorators.md +107 -0
  22. package/src/skills/nest-best-practices/references/fundamentals-dynamic-modules.md +125 -0
  23. package/src/skills/nest-best-practices/references/fundamentals-exception-filters.md +202 -0
  24. package/src/skills/nest-best-practices/references/fundamentals-execution-context.md +107 -0
  25. package/src/skills/nest-best-practices/references/fundamentals-guards.md +136 -0
  26. package/src/skills/nest-best-practices/references/fundamentals-interceptors.md +187 -0
  27. package/src/skills/nest-best-practices/references/fundamentals-lazy-loading.md +89 -0
  28. package/src/skills/nest-best-practices/references/fundamentals-lifecycle-events.md +87 -0
  29. package/src/skills/nest-best-practices/references/fundamentals-module-reference.md +107 -0
  30. package/src/skills/nest-best-practices/references/fundamentals-pipes.md +197 -0
  31. package/src/skills/nest-best-practices/references/fundamentals-provider-scopes.md +92 -0
  32. package/src/skills/nest-best-practices/references/fundamentals-testing.md +142 -0
  33. package/src/skills/nest-best-practices/references/graphql-overview.md +233 -0
  34. package/src/skills/nest-best-practices/references/graphql-resolvers-mutations.md +199 -0
  35. package/src/skills/nest-best-practices/references/graphql-scalars-unions-enums.md +180 -0
  36. package/src/skills/nest-best-practices/references/graphql-subscriptions.md +228 -0
  37. package/src/skills/nest-best-practices/references/microservices-grpc.md +175 -0
  38. package/src/skills/nest-best-practices/references/microservices-overview.md +221 -0
  39. package/src/skills/nest-best-practices/references/microservices-transports.md +119 -0
  40. package/src/skills/nest-best-practices/references/openapi-swagger.md +207 -0
  41. package/src/skills/nest-best-practices/references/recipes-authentication.md +97 -0
  42. package/src/skills/nest-best-practices/references/recipes-cqrs.md +176 -0
  43. package/src/skills/nest-best-practices/references/recipes-crud-generator.md +87 -0
  44. package/src/skills/nest-best-practices/references/recipes-documentation.md +93 -0
  45. package/src/skills/nest-best-practices/references/recipes-mongoose.md +153 -0
  46. package/src/skills/nest-best-practices/references/recipes-prisma.md +98 -0
  47. package/src/skills/nest-best-practices/references/recipes-terminus.md +148 -0
  48. package/src/skills/nest-best-practices/references/recipes-typeorm.md +122 -0
  49. package/src/skills/nest-best-practices/references/security-authorization.md +196 -0
  50. package/src/skills/nest-best-practices/references/security-cors-helmet-rate-limiting.md +204 -0
  51. package/src/skills/nest-best-practices/references/security-encryption-hashing.md +93 -0
  52. package/src/skills/nest-best-practices/references/techniques-caching.md +142 -0
  53. package/src/skills/nest-best-practices/references/techniques-compression-streaming-sse.md +194 -0
  54. package/src/skills/nest-best-practices/references/techniques-configuration.md +132 -0
  55. package/src/skills/nest-best-practices/references/techniques-database.md +153 -0
  56. package/src/skills/nest-best-practices/references/techniques-events.md +163 -0
  57. package/src/skills/nest-best-practices/references/techniques-fastify.md +137 -0
  58. package/src/skills/nest-best-practices/references/techniques-file-upload.md +140 -0
  59. package/src/skills/nest-best-practices/references/techniques-http-module.md +176 -0
  60. package/src/skills/nest-best-practices/references/techniques-logging.md +146 -0
  61. package/src/skills/nest-best-practices/references/techniques-mvc-serve-static.md +132 -0
  62. package/src/skills/nest-best-practices/references/techniques-queues.md +162 -0
  63. package/src/skills/nest-best-practices/references/techniques-serialization.md +158 -0
  64. package/src/skills/nest-best-practices/references/techniques-sessions-cookies.md +167 -0
  65. package/src/skills/nest-best-practices/references/techniques-task-scheduling.md +166 -0
  66. package/src/skills/nest-best-practices/references/techniques-validation.md +126 -0
  67. package/src/skills/nest-best-practices/references/techniques-versioning.md +153 -0
  68. package/src/skills/nest-best-practices/references/websockets-advanced.md +96 -0
  69. package/src/skills/nest-best-practices/references/websockets-gateways.md +215 -0
  70. package/src/skills/typescript-expert/SKILL.md +145 -0
  71. package/src/skills/typescript-expert/commands/typescript-fix.md +65 -0
  72. package/src/skills/typescript-expert/references/advanced-conditional-types.md +190 -0
  73. package/src/skills/typescript-expert/references/advanced-decorators.md +243 -0
  74. package/src/skills/typescript-expert/references/advanced-mapped-types.md +223 -0
  75. package/src/skills/typescript-expert/references/advanced-template-literals.md +209 -0
  76. package/src/skills/typescript-expert/references/advanced-type-guards.md +308 -0
  77. package/src/skills/typescript-expert/references/best-practices-patterns.md +313 -0
  78. package/src/skills/typescript-expert/references/best-practices-performance.md +185 -0
  79. package/src/skills/typescript-expert/references/best-practices-tsconfig.md +242 -0
  80. package/src/skills/typescript-expert/references/core-generics.md +246 -0
  81. package/src/skills/typescript-expert/references/core-interfaces-types.md +231 -0
  82. package/src/skills/typescript-expert/references/core-type-system.md +261 -0
  83. package/src/skills/typescript-expert/references/core-utility-types.md +235 -0
  84. package/src/skills/typescript-expert/references/features-ts5x.md +370 -0
@@ -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
+ -->