@neyugn/agent-kits 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +514 -0
  3. package/README.vi.md +410 -0
  4. package/README.zh.md +410 -0
  5. package/dist/cli.d.ts +1 -0
  6. package/dist/cli.js +422 -0
  7. package/kits/coder/ARCHITECTURE.md +289 -0
  8. package/kits/coder/agents/ai-engineer.md +344 -0
  9. package/kits/coder/agents/backend-specialist.md +270 -0
  10. package/kits/coder/agents/cloud-architect.md +363 -0
  11. package/kits/coder/agents/code-reviewer.md +284 -0
  12. package/kits/coder/agents/data-engineer.md +401 -0
  13. package/kits/coder/agents/database-specialist.md +251 -0
  14. package/kits/coder/agents/debugger.md +209 -0
  15. package/kits/coder/agents/devops-engineer.md +281 -0
  16. package/kits/coder/agents/documentation-writer.md +296 -0
  17. package/kits/coder/agents/frontend-specialist.md +298 -0
  18. package/kits/coder/agents/i18n-specialist.md +348 -0
  19. package/kits/coder/agents/integration-specialist.md +314 -0
  20. package/kits/coder/agents/mobile-developer.md +271 -0
  21. package/kits/coder/agents/multi-tenant-architect.md +281 -0
  22. package/kits/coder/agents/orchestrator.md +263 -0
  23. package/kits/coder/agents/performance-analyst.md +327 -0
  24. package/kits/coder/agents/project-planner.md +277 -0
  25. package/kits/coder/agents/queue-specialist.md +282 -0
  26. package/kits/coder/agents/realtime-specialist.md +267 -0
  27. package/kits/coder/agents/security-auditor.md +253 -0
  28. package/kits/coder/agents/test-engineer.md +315 -0
  29. package/kits/coder/agents/ux-researcher.md +388 -0
  30. package/kits/coder/rules/.cursorrules +287 -0
  31. package/kits/coder/rules/CLAUDE.md +287 -0
  32. package/kits/coder/rules/CODEX.md +287 -0
  33. package/kits/coder/rules/GEMINI.md +287 -0
  34. package/kits/coder/scripts/checklist.py +318 -0
  35. package/kits/coder/scripts/kit_status.py +292 -0
  36. package/kits/coder/scripts/skills_manager.py +243 -0
  37. package/kits/coder/scripts/verify_all.py +391 -0
  38. package/kits/coder/skills/accessibility-patterns/SKILL.md +372 -0
  39. package/kits/coder/skills/accessibility-patterns/scripts/a11y_checker.py +211 -0
  40. package/kits/coder/skills/ai-rag-patterns/SKILL.md +444 -0
  41. package/kits/coder/skills/api-patterns/SKILL.md +316 -0
  42. package/kits/coder/skills/api-patterns/assets/.gitkeep +1 -0
  43. package/kits/coder/skills/api-patterns/references/deep-dive.md +21 -0
  44. package/kits/coder/skills/api-patterns/scripts/api_validator.py +253 -0
  45. package/kits/coder/skills/api-patterns/scripts/validate.py +56 -0
  46. package/kits/coder/skills/auth-patterns/SKILL.md +267 -0
  47. package/kits/coder/skills/aws-patterns/SKILL.md +576 -0
  48. package/kits/coder/skills/brainstorming/SKILL.md +370 -0
  49. package/kits/coder/skills/brainstorming/assets/.gitkeep +1 -0
  50. package/kits/coder/skills/brainstorming/references/deep-dive.md +21 -0
  51. package/kits/coder/skills/brainstorming/scripts/validate.py +56 -0
  52. package/kits/coder/skills/clean-code/SKILL.md +240 -0
  53. package/kits/coder/skills/clean-code/assets/.gitkeep +1 -0
  54. package/kits/coder/skills/clean-code/references/deep-dive.md +21 -0
  55. package/kits/coder/skills/clean-code/scripts/lint_runner.py +186 -0
  56. package/kits/coder/skills/clean-code/scripts/validate.py +56 -0
  57. package/kits/coder/skills/database-design/SKILL.md +255 -0
  58. package/kits/coder/skills/database-design/assets/.gitkeep +1 -0
  59. package/kits/coder/skills/database-design/references/deep-dive.md +21 -0
  60. package/kits/coder/skills/database-design/scripts/schema_validator.py +272 -0
  61. package/kits/coder/skills/database-design/scripts/validate.py +56 -0
  62. package/kits/coder/skills/docker-patterns/SKILL.md +240 -0
  63. package/kits/coder/skills/documentation-templates/SKILL.md +441 -0
  64. package/kits/coder/skills/e2e-testing/SKILL.md +457 -0
  65. package/kits/coder/skills/flutter-patterns/SKILL.md +330 -0
  66. package/kits/coder/skills/frontend-design/SKILL.md +127 -0
  67. package/kits/coder/skills/github-actions/SKILL.md +349 -0
  68. package/kits/coder/skills/gitlab-ci-patterns/SKILL.md +466 -0
  69. package/kits/coder/skills/graphql-patterns/SKILL.md +558 -0
  70. package/kits/coder/skills/i18n-localization/SKILL.md +345 -0
  71. package/kits/coder/skills/i18n-localization/scripts/i18n_checker.py +267 -0
  72. package/kits/coder/skills/kubernetes-patterns/SKILL.md +357 -0
  73. package/kits/coder/skills/mermaid-diagrams/SKILL.md +351 -0
  74. package/kits/coder/skills/mobile-design/SKILL.md +305 -0
  75. package/kits/coder/skills/monitoring-observability/SKILL.md +458 -0
  76. package/kits/coder/skills/multi-tenancy/SKILL.md +317 -0
  77. package/kits/coder/skills/multi-tenancy/assets/.gitkeep +1 -0
  78. package/kits/coder/skills/multi-tenancy/references/deep-dive.md +21 -0
  79. package/kits/coder/skills/multi-tenancy/scripts/validate.py +56 -0
  80. package/kits/coder/skills/nodejs-best-practices/SKILL.md +220 -0
  81. package/kits/coder/skills/performance-profiling/SKILL.md +333 -0
  82. package/kits/coder/skills/performance-profiling/assets/.gitkeep +1 -0
  83. package/kits/coder/skills/performance-profiling/references/deep-dive.md +21 -0
  84. package/kits/coder/skills/performance-profiling/scripts/validate.py +56 -0
  85. package/kits/coder/skills/plan-writing/SKILL.md +360 -0
  86. package/kits/coder/skills/plan-writing/assets/.gitkeep +1 -0
  87. package/kits/coder/skills/plan-writing/references/deep-dive.md +21 -0
  88. package/kits/coder/skills/plan-writing/scripts/validate.py +56 -0
  89. package/kits/coder/skills/postgres-patterns/SKILL.md +361 -0
  90. package/kits/coder/skills/prompt-engineering/SKILL.md +277 -0
  91. package/kits/coder/skills/queue-patterns/SKILL.md +359 -0
  92. package/kits/coder/skills/queue-patterns/assets/.gitkeep +1 -0
  93. package/kits/coder/skills/queue-patterns/references/deep-dive.md +21 -0
  94. package/kits/coder/skills/queue-patterns/scripts/validate.py +56 -0
  95. package/kits/coder/skills/react-native-patterns/SKILL.md +393 -0
  96. package/kits/coder/skills/react-patterns/SKILL.md +319 -0
  97. package/kits/coder/skills/realtime-patterns/SKILL.md +506 -0
  98. package/kits/coder/skills/realtime-patterns/assets/.gitkeep +1 -0
  99. package/kits/coder/skills/realtime-patterns/references/deep-dive.md +21 -0
  100. package/kits/coder/skills/realtime-patterns/scripts/validate.py +56 -0
  101. package/kits/coder/skills/redis-patterns/SKILL.md +484 -0
  102. package/kits/coder/skills/security-fundamentals/SKILL.md +363 -0
  103. package/kits/coder/skills/security-fundamentals/assets/.gitkeep +1 -0
  104. package/kits/coder/skills/security-fundamentals/references/deep-dive.md +21 -0
  105. package/kits/coder/skills/security-fundamentals/scripts/security_scan.py +326 -0
  106. package/kits/coder/skills/security-fundamentals/scripts/validate.py +56 -0
  107. package/kits/coder/skills/seo-patterns/SKILL.md +262 -0
  108. package/kits/coder/skills/seo-patterns/scripts/seo_checker.py +211 -0
  109. package/kits/coder/skills/systematic-debugging/SKILL.md +478 -0
  110. package/kits/coder/skills/systematic-debugging/assets/.gitkeep +1 -0
  111. package/kits/coder/skills/systematic-debugging/references/deep-dive.md +21 -0
  112. package/kits/coder/skills/systematic-debugging/scripts/validate.py +56 -0
  113. package/kits/coder/skills/tailwind-patterns/SKILL.md +395 -0
  114. package/kits/coder/skills/terraform-patterns/SKILL.md +470 -0
  115. package/kits/coder/skills/testing-patterns/SKILL.md +285 -0
  116. package/kits/coder/skills/testing-patterns/assets/.gitkeep +1 -0
  117. package/kits/coder/skills/testing-patterns/references/deep-dive.md +21 -0
  118. package/kits/coder/skills/testing-patterns/scripts/test_runner.py +219 -0
  119. package/kits/coder/skills/testing-patterns/scripts/validate.py +56 -0
  120. package/kits/coder/skills/typescript-patterns/SKILL.md +417 -0
  121. package/kits/coder/skills/ui-ux-pro-max/SKILL.md +364 -0
  122. package/kits/coder/skills/ui-ux-pro-max/data/charts.csv +26 -0
  123. package/kits/coder/skills/ui-ux-pro-max/data/colors.csv +97 -0
  124. package/kits/coder/skills/ui-ux-pro-max/data/icons.csv +101 -0
  125. package/kits/coder/skills/ui-ux-pro-max/data/landing.csv +31 -0
  126. package/kits/coder/skills/ui-ux-pro-max/data/products.csv +97 -0
  127. package/kits/coder/skills/ui-ux-pro-max/data/prompts.csv +24 -0
  128. package/kits/coder/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  129. package/kits/coder/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  130. package/kits/coder/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  131. package/kits/coder/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  132. package/kits/coder/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  133. package/kits/coder/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  134. package/kits/coder/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  135. package/kits/coder/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  136. package/kits/coder/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  137. package/kits/coder/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  138. package/kits/coder/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  139. package/kits/coder/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  140. package/kits/coder/skills/ui-ux-pro-max/data/styles.csv +59 -0
  141. package/kits/coder/skills/ui-ux-pro-max/data/typography.csv +58 -0
  142. package/kits/coder/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  143. package/kits/coder/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  144. package/kits/coder/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  145. package/kits/coder/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-314.pyc +0 -0
  146. package/kits/coder/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-314.pyc +0 -0
  147. package/kits/coder/skills/ui-ux-pro-max/scripts/core.py +257 -0
  148. package/kits/coder/skills/ui-ux-pro-max/scripts/design_system.py +488 -0
  149. package/kits/coder/skills/ui-ux-pro-max/scripts/search.py +76 -0
  150. package/kits/coder/workflows/.gitkeep +20 -0
  151. package/kits/coder/workflows/create.md +152 -0
  152. package/kits/coder/workflows/debug.md +223 -0
  153. package/kits/coder/workflows/deploy.md +283 -0
  154. package/kits/coder/workflows/orchestrate.md +243 -0
  155. package/kits/coder/workflows/plan.md +134 -0
  156. package/kits/coder/workflows/test.md +237 -0
  157. package/kits/coder/workflows/ui-ux-pro-max.md +109 -0
  158. package/package.json +49 -0
@@ -0,0 +1,558 @@
1
+ ---
2
+ name: graphql-patterns
3
+ description: GraphQL API design, schema patterns, and performance optimization. Use when designing GraphQL schemas, implementing resolvers, preventing N+1 queries, or building federated architectures.
4
+ allowed-tools: Read, Write, Edit, Glob, Grep
5
+ version: 2.0
6
+ ---
7
+
8
+ # GraphQL Patterns - API Design & Performance
9
+
10
+ > **Philosophy:** GraphQL is a contract, not just an API. The schema IS documentation. Design it carefully.
11
+
12
+ ---
13
+
14
+ ## When to Use This Skill
15
+
16
+ | ✅ Use | ❌ Don't Use |
17
+ | --------------------------- | -------------------------------- |
18
+ | Schema design | REST API design |
19
+ | Resolver implementation | Database queries (use ORM) |
20
+ | N+1 prevention (DataLoader) | Client-side caching (use Apollo) |
21
+ | Federation architecture | Simple CRUD APIs |
22
+ | Real-time subscriptions | File uploads as primary use |
23
+ | Query optimization | Rate limiting (use middleware) |
24
+
25
+ ➡️ For REST patterns, see `api-patterns` skill.
26
+
27
+ ---
28
+
29
+ ## Core Rules (Non-Negotiable)
30
+
31
+ 1. **DataLoader mandatory** - Every resolver with DB calls needs DataLoader
32
+ 2. **Depth limiting required** - Prevent deep query attacks
33
+ 3. **Explicit nullability** - Design nullability intentionally
34
+ 4. **Auth in resolvers** - Never rely on schema directives alone
35
+ 5. **Disable introspection** - Production must disable introspection
36
+
37
+ ---
38
+
39
+ ## Schema Design Principles
40
+
41
+ ### Type Design
42
+
43
+ ```graphql
44
+ # ✅ Good: Explicit nullability, clear types
45
+ type User {
46
+ id: ID! # Always non-null
47
+ email: String! # Required field
48
+ name: String!
49
+ bio: String # Optional (nullable)
50
+ avatar: String
51
+ posts(first: Int): [Post!]! # List of non-null posts, list itself non-null
52
+ createdAt: DateTime!
53
+ }
54
+
55
+ # ✅ Good: Input types for mutations
56
+ input CreateUserInput {
57
+ email: String!
58
+ name: String!
59
+ bio: String
60
+ }
61
+
62
+ input UpdateUserInput {
63
+ name: String
64
+ bio: String
65
+ }
66
+ ```
67
+
68
+ ### Nullability Strategy
69
+
70
+ | Pattern | Meaning |
71
+ | ------------ | ----------------------------------- |
72
+ | `String` | May be null (optional field) |
73
+ | `String!` | Never null (required) |
74
+ | `[String]` | List may be null, items may be null |
75
+ | `[String]!` | List never null, items may be null |
76
+ | `[String!]` | List may be null, items never null |
77
+ | `[String!]!` | List never null, items never null |
78
+
79
+ **Recommendation:** Use `[Type!]!` for lists (empty list over null).
80
+
81
+ ### Relay Connection Pattern
82
+
83
+ ```graphql
84
+ type Query {
85
+ users(
86
+ first: Int
87
+ after: String
88
+ last: Int
89
+ before: String
90
+ filter: UserFilter
91
+ ): UserConnection!
92
+ }
93
+
94
+ type UserConnection {
95
+ edges: [UserEdge!]!
96
+ pageInfo: PageInfo!
97
+ totalCount: Int!
98
+ }
99
+
100
+ type UserEdge {
101
+ cursor: String!
102
+ node: User!
103
+ }
104
+
105
+ type PageInfo {
106
+ hasNextPage: Boolean!
107
+ hasPreviousPage: Boolean!
108
+ startCursor: String
109
+ endCursor: String
110
+ }
111
+ ```
112
+
113
+ ---
114
+
115
+ ## DataLoader Pattern (N+1 Prevention)
116
+
117
+ ### The Problem
118
+
119
+ ```typescript
120
+ // ❌ N+1: Each user triggers separate DB query
121
+ const resolvers = {
122
+ Post: {
123
+ author: (post) => db.users.findById(post.authorId), // N queries!
124
+ },
125
+ };
126
+ ```
127
+
128
+ ### The Solution
129
+
130
+ ```typescript
131
+ import DataLoader from "dataloader";
132
+
133
+ // Create loader (per-request)
134
+ function createLoaders() {
135
+ return {
136
+ userLoader: new DataLoader(async (userIds: string[]) => {
137
+ const users = await db.users.findByIds(userIds);
138
+ // MUST return in same order as input
139
+ return userIds.map((id) => users.find((u) => u.id === id) || null);
140
+ }),
141
+
142
+ postsByUserLoader: new DataLoader(async (userIds: string[]) => {
143
+ const posts = await db.posts.findByUserIds(userIds);
144
+ // Group by userId
145
+ return userIds.map((id) => posts.filter((p) => p.authorId === id));
146
+ }),
147
+ };
148
+ }
149
+
150
+ // Use in resolver
151
+ const resolvers = {
152
+ Post: {
153
+ author: (post, _, { loaders }) => loaders.userLoader.load(post.authorId),
154
+ },
155
+ User: {
156
+ posts: (user, _, { loaders }) => loaders.postsByUserLoader.load(user.id),
157
+ },
158
+ };
159
+
160
+ // Context creation
161
+ const context = ({ req }) => ({
162
+ loaders: createLoaders(),
163
+ user: getUserFromToken(req),
164
+ });
165
+ ```
166
+
167
+ ### DataLoader Rules
168
+
169
+ 1. **Create per-request** - New instance for each GraphQL request
170
+ 2. **Batch must match order** - Return results in exact input order
171
+ 3. **Handle missing items** - Return null for not-found
172
+ 4. **Key uniqueness** - Convert to string if complex keys
173
+
174
+ ---
175
+
176
+ ## Query Optimization
177
+
178
+ ### Depth Limiting
179
+
180
+ ```typescript
181
+ import depthLimit from "graphql-depth-limit";
182
+
183
+ const server = new ApolloServer({
184
+ typeDefs,
185
+ resolvers,
186
+ validationRules: [depthLimit(10)], // Max 10 levels deep
187
+ });
188
+ ```
189
+
190
+ ### Query Complexity
191
+
192
+ ```typescript
193
+ import { createComplexityLimitRule } from "graphql-validation-complexity";
194
+
195
+ const complexityLimitRule = createComplexityLimitRule(1000, {
196
+ onCost: (cost) => console.log("Query cost:", cost),
197
+ scalarCost: 1,
198
+ objectCost: 2,
199
+ listFactor: 10,
200
+ });
201
+
202
+ const server = new ApolloServer({
203
+ validationRules: [complexityLimitRule],
204
+ });
205
+ ```
206
+
207
+ ### Field Cost Analysis
208
+
209
+ ```graphql
210
+ type Query {
211
+ users(first: Int): [User!]! @cost(complexity: 10, multipliers: ["first"])
212
+ user(id: ID!): User @cost(complexity: 1)
213
+ }
214
+
215
+ type User {
216
+ id: ID!
217
+ name: String!
218
+ posts: [Post!]! @cost(complexity: 5) # More expensive field
219
+ }
220
+ ```
221
+
222
+ ---
223
+
224
+ ## Authorization Patterns
225
+
226
+ ### Resolver-Level Auth (Recommended)
227
+
228
+ ```typescript
229
+ const resolvers = {
230
+ Query: {
231
+ user: async (_, { id }, { user }) => {
232
+ if (!user) throw new AuthenticationError("Not authenticated");
233
+
234
+ const targetUser = await db.users.findById(id);
235
+
236
+ // Authorization logic
237
+ if (user.role !== "admin" && user.id !== id) {
238
+ throw new ForbiddenError("Not authorized");
239
+ }
240
+
241
+ return targetUser;
242
+ },
243
+ },
244
+
245
+ User: {
246
+ email: (user, _, { currentUser }) => {
247
+ // Field-level authorization
248
+ if (currentUser?.id === user.id || currentUser?.role === "admin") {
249
+ return user.email;
250
+ }
251
+ return null; // Hide from unauthorized users
252
+ },
253
+ },
254
+ };
255
+ ```
256
+
257
+ ### Directive-Based Auth (Supplement, not replace)
258
+
259
+ ```graphql
260
+ directive @auth(requires: Role = USER) on FIELD_DEFINITION
261
+ directive @owner on FIELD_DEFINITION
262
+
263
+ type Query {
264
+ users: [User!]! @auth(requires: ADMIN)
265
+ me: User @auth
266
+ }
267
+
268
+ type User {
269
+ id: ID!
270
+ name: String!
271
+ email: String! @owner # Only owner can see
272
+ secretField: String @auth(requires: ADMIN)
273
+ }
274
+ ```
275
+
276
+ ---
277
+
278
+ ## Error Handling
279
+
280
+ ### Structured Errors
281
+
282
+ ```typescript
283
+ class UserInputError extends Error {
284
+ constructor(
285
+ message: string,
286
+ public extensions: Record<string, any>,
287
+ ) {
288
+ super(message);
289
+ }
290
+ }
291
+
292
+ const resolvers = {
293
+ Mutation: {
294
+ createUser: async (_, { input }) => {
295
+ const errors: Record<string, string> = {};
296
+
297
+ if (!isValidEmail(input.email)) {
298
+ errors.email = "Invalid email format";
299
+ }
300
+
301
+ if (Object.keys(errors).length > 0) {
302
+ throw new UserInputError("Validation failed", {
303
+ validationErrors: errors,
304
+ code: "VALIDATION_ERROR",
305
+ });
306
+ }
307
+
308
+ return db.users.create(input);
309
+ },
310
+ },
311
+ };
312
+ ```
313
+
314
+ ### Union Types for Errors
315
+
316
+ ```graphql
317
+ type Mutation {
318
+ createUser(input: CreateUserInput!): CreateUserResult!
319
+ }
320
+
321
+ union CreateUserResult = User | ValidationError | EmailTakenError
322
+
323
+ type ValidationError {
324
+ message: String!
325
+ field: String!
326
+ }
327
+
328
+ type EmailTakenError {
329
+ message: String!
330
+ suggestedEmail: String
331
+ }
332
+ ```
333
+
334
+ ---
335
+
336
+ ## Subscriptions
337
+
338
+ ### Basic Subscription
339
+
340
+ ```typescript
341
+ import { PubSub } from "graphql-subscriptions";
342
+
343
+ const pubsub = new PubSub();
344
+
345
+ const resolvers = {
346
+ Mutation: {
347
+ sendMessage: async (_, { input }, { user }) => {
348
+ const message = await db.messages.create({
349
+ ...input,
350
+ authorId: user.id,
351
+ });
352
+
353
+ // Publish event
354
+ pubsub.publish(`CHAT_${input.chatId}`, {
355
+ messageSent: message,
356
+ });
357
+
358
+ return message;
359
+ },
360
+ },
361
+
362
+ Subscription: {
363
+ messageSent: {
364
+ subscribe: (_, { chatId }, { user }) => {
365
+ // Auth check
366
+ if (!user) throw new AuthenticationError("Not authenticated");
367
+
368
+ return pubsub.asyncIterator(`CHAT_${chatId}`);
369
+ },
370
+ },
371
+ },
372
+ };
373
+ ```
374
+
375
+ ### Filtered Subscriptions
376
+
377
+ ```typescript
378
+ import { withFilter } from "graphql-subscriptions";
379
+
380
+ const resolvers = {
381
+ Subscription: {
382
+ messageSent: {
383
+ subscribe: withFilter(
384
+ () => pubsub.asyncIterator("MESSAGE_CREATED"),
385
+ (payload, variables, context) => {
386
+ // Only deliver to users in the chat
387
+ return (
388
+ payload.messageSent.chatId === variables.chatId &&
389
+ context.user.chats.includes(variables.chatId)
390
+ );
391
+ },
392
+ ),
393
+ },
394
+ },
395
+ };
396
+ ```
397
+
398
+ ---
399
+
400
+ ## Federation Pattern
401
+
402
+ ### Subgraph Schema
403
+
404
+ ```graphql
405
+ # Users Service
406
+ type User @key(fields: "id") {
407
+ id: ID!
408
+ name: String!
409
+ email: String!
410
+ }
411
+
412
+ extend type Query {
413
+ user(id: ID!): User
414
+ me: User
415
+ }
416
+
417
+ # Posts Service
418
+ type Post @key(fields: "id") {
419
+ id: ID!
420
+ title: String!
421
+ content: String!
422
+ author: User!
423
+ }
424
+
425
+ # Extend User from Users Service
426
+ extend type User @key(fields: "id") {
427
+ id: ID! @external
428
+ posts: [Post!]!
429
+ }
430
+ ```
431
+
432
+ ### Reference Resolver
433
+
434
+ ```typescript
435
+ // Posts service resolves User reference
436
+ const resolvers = {
437
+ User: {
438
+ __resolveReference: (user) => {
439
+ // user contains { id } from key
440
+ return { id: user.id }; // Minimal stub, Users service fills rest
441
+ },
442
+ posts: (user) => db.posts.findByAuthorId(user.id),
443
+ },
444
+ };
445
+ ```
446
+
447
+ ---
448
+
449
+ ## Caching Strategies
450
+
451
+ ### CDN/Response Caching
452
+
453
+ ```typescript
454
+ const resolvers = {
455
+ Query: {
456
+ // Public, cacheable
457
+ products: () => db.products.findAll(),
458
+ },
459
+
460
+ Product: {
461
+ __cacheControl: { maxAge: 3600, scope: "PUBLIC" },
462
+ },
463
+
464
+ User: {
465
+ __cacheControl: { maxAge: 0, scope: "PRIVATE" },
466
+ email: {
467
+ __cacheControl: { maxAge: 0 }, // Never cache sensitive data
468
+ },
469
+ },
470
+ };
471
+ ```
472
+
473
+ ### Automatic Persisted Queries (APQ)
474
+
475
+ ```typescript
476
+ import { ApolloServer } from "@apollo/server";
477
+
478
+ const server = new ApolloServer({
479
+ typeDefs,
480
+ resolvers,
481
+ persistedQueries: {
482
+ ttl: 900, // 15 minutes
483
+ },
484
+ });
485
+ ```
486
+
487
+ ---
488
+
489
+ ## Production Security Checklist
490
+
491
+ ```typescript
492
+ const server = new ApolloServer({
493
+ typeDefs,
494
+ resolvers,
495
+
496
+ // ✅ Disable introspection in production
497
+ introspection: process.env.NODE_ENV !== "production",
498
+
499
+ // ✅ Disable playground in production
500
+ playground: process.env.NODE_ENV !== "production",
501
+
502
+ // ✅ Validation rules
503
+ validationRules: [depthLimit(10), createComplexityLimitRule(1000)],
504
+
505
+ // ✅ Error formatting (hide internal details)
506
+ formatError: (error) => {
507
+ if (process.env.NODE_ENV === "production") {
508
+ return { message: error.message };
509
+ }
510
+ return error;
511
+ },
512
+ });
513
+ ```
514
+
515
+ ---
516
+
517
+ ## Anti-Patterns
518
+
519
+ | ❌ Don't | ✅ Do |
520
+ | ------------------------------------- | ------------------------------------------- |
521
+ | Resolver makes DB call without loader | Use DataLoader for all DB access |
522
+ | All fields nullable | Design nullability intentionally |
523
+ | Auth only in directives | Auth in resolvers, directives as supplement |
524
+ | Introspection in production | Disable introspection |
525
+ | Deep unlimited queries | Depth limiting + complexity analysis |
526
+ | Return all errors as same type | Use union types for error variants |
527
+ | Create DataLoader once globally | Create per-request |
528
+ | Subscription without auth check | Check auth in subscribe function |
529
+
530
+ ---
531
+
532
+ ## Performance Checklist
533
+
534
+ Before production:
535
+
536
+ - [ ] DataLoader for all nested resolvers?
537
+ - [ ] Depth limit configured?
538
+ - [ ] Query complexity analysis?
539
+ - [ ] Introspection disabled?
540
+ - [ ] Error details hidden in production?
541
+ - [ ] Subscription auth implemented?
542
+ - [ ] Persisted queries enabled?
543
+ - [ ] Cache headers set appropriately?
544
+
545
+ ---
546
+
547
+ ## Related Skills
548
+
549
+ | Need | Skill |
550
+ | ---------------------- | --------------------- |
551
+ | REST API design | `api-patterns` |
552
+ | Database queries | `database-design` |
553
+ | Real-time patterns | `realtime-patterns` |
554
+ | TypeScript integration | `typescript-patterns` |
555
+
556
+ ---
557
+
558
+ > **Remember:** GraphQL's flexibility is its power and danger. Protect your API with DataLoader, depth limits, and auth at every level.