@codyswann/lisa 1.47.0 → 1.48.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 (216) hide show
  1. package/all/copy-overwrite/.claude/rules/lisa.md +23 -10
  2. package/all/copy-overwrite/.claude/settings.json +10 -230
  3. package/all/deletions.json +67 -1
  4. package/cdk/copy-overwrite/.claude/settings.json +80 -0
  5. package/cdk/create-only/.github/workflows/ci.yml +1 -1
  6. package/cdk/create-only/.github/workflows/deploy.yml +1 -1
  7. package/dist/core/lisa.d.ts +14 -0
  8. package/dist/core/lisa.d.ts.map +1 -1
  9. package/dist/core/lisa.js +47 -0
  10. package/dist/core/lisa.js.map +1 -1
  11. package/expo/copy-overwrite/.claude/settings.json +80 -0
  12. package/expo/copy-overwrite/eslint.expo.ts +2 -2
  13. package/expo/create-only/.github/workflows/ci.yml +1 -1
  14. package/expo/create-only/.github/workflows/deploy.yml +1 -1
  15. package/expo/deletions.json +33 -0
  16. package/expo/package-lisa/package.lisa.json +2 -2
  17. package/nestjs/copy-overwrite/.claude/settings.json +80 -0
  18. package/nestjs/create-only/.github/workflows/ci.yml +1 -1
  19. package/nestjs/create-only/.github/workflows/deploy.yml +1 -1
  20. package/nestjs/deletions.json +8 -0
  21. package/package.json +8 -4
  22. package/rails/copy-overwrite/.claude/settings.json +80 -0
  23. package/rails/create-only/.github/workflows/ci.yml +1 -1
  24. package/rails/deletions.json +11 -1
  25. package/typescript/copy-overwrite/.claude/settings.json +13 -231
  26. package/typescript/copy-overwrite/.github/workflows/claude-ci-auto-fix.yml +1 -0
  27. package/typescript/copy-overwrite/.github/workflows/claude-code-review-response.yml +11 -10
  28. package/typescript/copy-overwrite/.github/workflows/claude-deploy-auto-fix.yml +1 -0
  29. package/typescript/copy-overwrite/.github/workflows/claude-nightly-code-complexity.yml +1 -0
  30. package/typescript/copy-overwrite/.github/workflows/claude-nightly-test-coverage.yml +1 -0
  31. package/typescript/copy-overwrite/.github/workflows/claude-nightly-test-improvement.yml +2 -0
  32. package/typescript/copy-overwrite/.github/workflows/claude.yml +1 -0
  33. package/typescript/copy-overwrite/eslint.typescript.ts +1 -1
  34. package/typescript/create-only/.github/workflows/ci.yml +1 -1
  35. package/typescript/deletions.json +12 -1
  36. package/typescript/package-lisa/package.lisa.json +1 -1
  37. package/all/copy-overwrite/.claude/agents/agent-architect.md +0 -310
  38. package/all/copy-overwrite/.claude/agents/architecture-specialist.md +0 -53
  39. package/all/copy-overwrite/.claude/agents/debug-specialist.md +0 -204
  40. package/all/copy-overwrite/.claude/agents/git-history-analyzer.md +0 -183
  41. package/all/copy-overwrite/.claude/agents/hooks-expert.md +0 -74
  42. package/all/copy-overwrite/.claude/agents/implementer.md +0 -54
  43. package/all/copy-overwrite/.claude/agents/learner.md +0 -44
  44. package/all/copy-overwrite/.claude/agents/performance-specialist.md +0 -95
  45. package/all/copy-overwrite/.claude/agents/product-specialist.md +0 -72
  46. package/all/copy-overwrite/.claude/agents/quality-specialist.md +0 -55
  47. package/all/copy-overwrite/.claude/agents/security-specialist.md +0 -58
  48. package/all/copy-overwrite/.claude/agents/skill-evaluator.md +0 -246
  49. package/all/copy-overwrite/.claude/agents/slash-command-architect.md +0 -87
  50. package/all/copy-overwrite/.claude/agents/test-specialist.md +0 -64
  51. package/all/copy-overwrite/.claude/agents/verification-specialist.md +0 -189
  52. package/all/copy-overwrite/.claude/agents/web-search-researcher.md +0 -112
  53. package/all/copy-overwrite/.claude/commands/git/commit-and-submit-pr.md +0 -7
  54. package/all/copy-overwrite/.claude/commands/git/commit-submit-pr-and-verify.md +0 -7
  55. package/all/copy-overwrite/.claude/commands/git/commit-submit-pr-deploy-and-verify.md +0 -7
  56. package/all/copy-overwrite/.claude/commands/git/commit.md +0 -7
  57. package/all/copy-overwrite/.claude/commands/git/prune.md +0 -6
  58. package/all/copy-overwrite/.claude/commands/git/submit-pr.md +0 -7
  59. package/all/copy-overwrite/.claude/commands/jira/create.md +0 -7
  60. package/all/copy-overwrite/.claude/commands/jira/sync.md +0 -7
  61. package/all/copy-overwrite/.claude/commands/jira/verify.md +0 -7
  62. package/all/copy-overwrite/.claude/commands/lisa/review-implementation.md +0 -7
  63. package/all/copy-overwrite/.claude/commands/plan/add-test-coverage.md +0 -7
  64. package/all/copy-overwrite/.claude/commands/plan/create.md +0 -6
  65. package/all/copy-overwrite/.claude/commands/plan/execute.md +0 -7
  66. package/all/copy-overwrite/.claude/commands/plan/fix-linter-error.md +0 -7
  67. package/all/copy-overwrite/.claude/commands/plan/local-code-review.md +0 -6
  68. package/all/copy-overwrite/.claude/commands/plan/lower-code-complexity.md +0 -6
  69. package/all/copy-overwrite/.claude/commands/plan/reduce-max-lines-per-function.md +0 -7
  70. package/all/copy-overwrite/.claude/commands/plan/reduce-max-lines.md +0 -7
  71. package/all/copy-overwrite/.claude/commands/pull-request/review.md +0 -7
  72. package/all/copy-overwrite/.claude/commands/security/zap-scan.md +0 -6
  73. package/all/copy-overwrite/.claude/commands/sonarqube/check.md +0 -6
  74. package/all/copy-overwrite/.claude/commands/sonarqube/fix.md +0 -6
  75. package/all/copy-overwrite/.claude/commands/tasks/load.md +0 -7
  76. package/all/copy-overwrite/.claude/commands/tasks/sync.md +0 -7
  77. package/all/copy-overwrite/.claude/hooks/check-tired-boss.sh +0 -61
  78. package/all/copy-overwrite/.claude/hooks/debug-hook.sh +0 -47
  79. package/all/copy-overwrite/.claude/hooks/enforce-plan-rules.sh +0 -15
  80. package/all/copy-overwrite/.claude/hooks/notify-ntfy.sh +0 -183
  81. package/all/copy-overwrite/.claude/hooks/setup-jira-cli.sh +0 -52
  82. package/all/copy-overwrite/.claude/hooks/sync-tasks.sh +0 -107
  83. package/all/copy-overwrite/.claude/hooks/ticket-sync-reminder.sh +0 -23
  84. package/all/copy-overwrite/.claude/hooks/track-plan-sessions.sh +0 -164
  85. package/all/copy-overwrite/.claude/rules/coding-philosophy.md +0 -428
  86. package/all/copy-overwrite/.claude/rules/verfication.md +0 -541
  87. package/all/copy-overwrite/.claude/skills/agent-design-best-practices/SKILL.md +0 -219
  88. package/all/copy-overwrite/.claude/skills/git-commit/SKILL.md +0 -48
  89. package/all/copy-overwrite/.claude/skills/git-commit-and-submit-pr/SKILL.md +0 -8
  90. package/all/copy-overwrite/.claude/skills/git-commit-submit-pr-and-verify/SKILL.md +0 -7
  91. package/all/copy-overwrite/.claude/skills/git-commit-submit-pr-deploy-and-verify/SKILL.md +0 -7
  92. package/all/copy-overwrite/.claude/skills/git-prune/SKILL.md +0 -35
  93. package/all/copy-overwrite/.claude/skills/git-submit-pr/SKILL.md +0 -44
  94. package/all/copy-overwrite/.claude/skills/jira-create/SKILL.md +0 -41
  95. package/all/copy-overwrite/.claude/skills/jira-sync/SKILL.md +0 -63
  96. package/all/copy-overwrite/.claude/skills/jira-verify/SKILL.md +0 -29
  97. package/all/copy-overwrite/.claude/skills/lisa-review-implementation/SKILL.md +0 -209
  98. package/all/copy-overwrite/.claude/skills/plan-add-test-coverage/SKILL.md +0 -44
  99. package/all/copy-overwrite/.claude/skills/plan-execute/SKILL.md +0 -89
  100. package/all/copy-overwrite/.claude/skills/plan-fix-linter-error/SKILL.md +0 -45
  101. package/all/copy-overwrite/.claude/skills/plan-local-code-review/SKILL.md +0 -88
  102. package/all/copy-overwrite/.claude/skills/plan-lower-code-complexity/SKILL.md +0 -44
  103. package/all/copy-overwrite/.claude/skills/plan-reduce-max-lines/SKILL.md +0 -45
  104. package/all/copy-overwrite/.claude/skills/plan-reduce-max-lines-per-function/SKILL.md +0 -46
  105. package/all/copy-overwrite/.claude/skills/pull-request-review/SKILL.md +0 -68
  106. package/all/copy-overwrite/.claude/skills/security-zap-scan/SKILL.md +0 -33
  107. package/all/copy-overwrite/.claude/skills/skill-creator/LICENSE.txt +0 -202
  108. package/all/copy-overwrite/.claude/skills/skill-creator/SKILL.md +0 -210
  109. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/__pycache__/quick_validate.cpython-312.pyc +0 -0
  110. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/init_skill.py +0 -305
  111. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/package_skill.py +0 -112
  112. package/all/copy-overwrite/.claude/skills/skill-creator/scripts/quick_validate.py +0 -67
  113. package/all/copy-overwrite/.claude/skills/sonarqube-check/SKILL.md +0 -11
  114. package/all/copy-overwrite/.claude/skills/sonarqube-fix/SKILL.md +0 -8
  115. package/all/copy-overwrite/.claude/skills/tasks-load/SKILL.md +0 -88
  116. package/all/copy-overwrite/.claude/skills/tasks-sync/SKILL.md +0 -108
  117. package/eslint-plugin-code-organization/README.md +0 -149
  118. package/eslint-plugin-code-organization/__tests__/enforce-statement-order.test.js +0 -473
  119. package/eslint-plugin-code-organization/index.js +0 -28
  120. package/eslint-plugin-code-organization/package.json +0 -10
  121. package/eslint-plugin-code-organization/rules/enforce-statement-order.js +0 -162
  122. package/expo/copy-overwrite/.claude/agents/ops-specialist.md +0 -124
  123. package/expo/copy-overwrite/.claude/rules/expo-verification.md +0 -261
  124. package/expo/copy-overwrite/.claude/skills/apollo-client/SKILL.md +0 -238
  125. package/expo/copy-overwrite/.claude/skills/apollo-client/references/mutation-patterns.md +0 -360
  126. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/SKILL.md +0 -360
  127. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/atomic-levels.md +0 -417
  128. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/folder-structure.md +0 -257
  129. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/gluestack-mapping.md +0 -233
  130. package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/scripts/validate_atomic_structure.py +0 -329
  131. package/expo/copy-overwrite/.claude/skills/container-view-pattern/SKILL.md +0 -299
  132. package/expo/copy-overwrite/.claude/skills/container-view-pattern/references/examples.md +0 -749
  133. package/expo/copy-overwrite/.claude/skills/container-view-pattern/references/patterns.md +0 -318
  134. package/expo/copy-overwrite/.claude/skills/container-view-pattern/scripts/create_component.py +0 -200
  135. package/expo/copy-overwrite/.claude/skills/container-view-pattern/scripts/validate_component.py +0 -209
  136. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/SKILL.md +0 -268
  137. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/common-issues.md +0 -619
  138. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/file-extensions.md +0 -340
  139. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/platform-api.md +0 -276
  140. package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/scripts/validate_cross_platform.py +0 -416
  141. package/expo/copy-overwrite/.claude/skills/directory-structure/SKILL.md +0 -202
  142. package/expo/copy-overwrite/.claude/skills/directory-structure/scripts/validate_structure.py +0 -445
  143. package/expo/copy-overwrite/.claude/skills/expo-env-config/SKILL.md +0 -309
  144. package/expo/copy-overwrite/.claude/skills/expo-env-config/references/validation-patterns.md +0 -417
  145. package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/SKILL.md +0 -431
  146. package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/references/official-docs.md +0 -290
  147. package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/scripts/generate-route.py +0 -171
  148. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/SKILL.md +0 -411
  149. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/color-tokens.md +0 -343
  150. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/component-mapping.md +0 -307
  151. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/spacing-scale.md +0 -300
  152. package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/scripts/validate_styling.py +0 -315
  153. package/expo/copy-overwrite/.claude/skills/local-state/SKILL.md +0 -362
  154. package/expo/copy-overwrite/.claude/skills/local-state/references/async-storage.md +0 -505
  155. package/expo/copy-overwrite/.claude/skills/local-state/references/persistence-patterns.md +0 -711
  156. package/expo/copy-overwrite/.claude/skills/local-state/references/reactive-variables.md +0 -446
  157. package/expo/copy-overwrite/.claude/skills/ops-browser-uat/SKILL.md +0 -124
  158. package/expo/copy-overwrite/.claude/skills/ops-check-logs/SKILL.md +0 -211
  159. package/expo/copy-overwrite/.claude/skills/ops-db-ops/SKILL.md +0 -119
  160. package/expo/copy-overwrite/.claude/skills/ops-deploy/SKILL.md +0 -119
  161. package/expo/copy-overwrite/.claude/skills/ops-monitor-errors/SKILL.md +0 -99
  162. package/expo/copy-overwrite/.claude/skills/ops-performance/SKILL.md +0 -165
  163. package/expo/copy-overwrite/.claude/skills/ops-run-local/SKILL.md +0 -166
  164. package/expo/copy-overwrite/.claude/skills/ops-verify-health/SKILL.md +0 -101
  165. package/expo/copy-overwrite/.claude/skills/owasp-zap/SKILL.md +0 -56
  166. package/expo/copy-overwrite/.claude/skills/playwright-selectors/SKILL.md +0 -223
  167. package/expo/copy-overwrite/.claude/skills/testing-library/SKILL.md +0 -314
  168. package/expo/copy-overwrite/.claude/skills/testing-library/references/async-patterns.md +0 -420
  169. package/expo/copy-overwrite/.claude/skills/testing-library/references/expo-router-testing.md +0 -556
  170. package/expo/copy-overwrite/.claude/skills/testing-library/references/mocking-patterns.md +0 -590
  171. package/expo/copy-overwrite/.claude/skills/testing-library/references/query-priority.md +0 -291
  172. package/expo/copy-overwrite/eslint-plugin-component-structure/README.md +0 -234
  173. package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/plugin-index.test.js +0 -89
  174. package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/require-memo-in-view.test.js +0 -201
  175. package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/single-component-per-file.test.js +0 -294
  176. package/expo/copy-overwrite/eslint-plugin-component-structure/index.js +0 -37
  177. package/expo/copy-overwrite/eslint-plugin-component-structure/package.json +0 -10
  178. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/enforce-component-structure.js +0 -235
  179. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/no-return-in-view.js +0 -96
  180. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/require-memo-in-view.js +0 -183
  181. package/expo/copy-overwrite/eslint-plugin-component-structure/rules/single-component-per-file.js +0 -243
  182. package/expo/copy-overwrite/eslint-plugin-ui-standards/README.md +0 -192
  183. package/expo/copy-overwrite/eslint-plugin-ui-standards/index.js +0 -31
  184. package/expo/copy-overwrite/eslint-plugin-ui-standards/package.json +0 -10
  185. package/expo/copy-overwrite/eslint-plugin-ui-standards/rules/no-classname-outside-ui.js +0 -56
  186. package/expo/copy-overwrite/eslint-plugin-ui-standards/rules/no-direct-rn-imports.js +0 -60
  187. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/SKILL.md +0 -176
  188. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/advanced-features.md +0 -527
  189. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/project-patterns.md +0 -483
  190. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/quick-start.md +0 -257
  191. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/resolvers-mutations.md +0 -413
  192. package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/types-scalars.md +0 -513
  193. package/nestjs/copy-overwrite/.claude/skills/nestjs-rules/SKILL.md +0 -536
  194. package/nestjs/copy-overwrite/.claude/skills/security-zap-scan/SKILL.md +0 -33
  195. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/SKILL.md +0 -275
  196. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/configuration-patterns.md +0 -487
  197. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/entity-patterns.md +0 -450
  198. package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/observability-patterns.md +0 -536
  199. package/rails/copy-overwrite/.claude/skills/action-controller-best-practices/SKILL.md +0 -374
  200. package/rails/copy-overwrite/.claude/skills/action-view-best-practices/SKILL.md +0 -335
  201. package/rails/copy-overwrite/.claude/skills/active-record-model-best-practices/SKILL.md +0 -166
  202. package/rails/copy-overwrite/.claude/skills/plan-add-test-coverage/SKILL.md +0 -45
  203. package/rails/copy-overwrite/.claude/skills/plan-fix-linter-error/SKILL.md +0 -45
  204. package/rails/copy-overwrite/.claude/skills/plan-lower-code-complexity/SKILL.md +0 -48
  205. package/rails/copy-overwrite/.claude/skills/plan-reduce-max-lines/SKILL.md +0 -46
  206. package/rails/copy-overwrite/.claude/skills/plan-reduce-max-lines-per-function/SKILL.md +0 -46
  207. package/typescript/copy-overwrite/.claude/hooks/format-on-edit.sh +0 -76
  208. package/typescript/copy-overwrite/.claude/hooks/install-pkgs.sh +0 -64
  209. package/typescript/copy-overwrite/.claude/hooks/lint-on-edit.sh +0 -105
  210. package/typescript/copy-overwrite/.claude/hooks/sg-scan-on-edit.sh +0 -68
  211. package/typescript/copy-overwrite/.claude/skills/jsdoc-best-practices/SKILL.md +0 -432
  212. package/typescript/copy-overwrite/eslint-plugin-code-organization/README.md +0 -149
  213. package/typescript/copy-overwrite/eslint-plugin-code-organization/__tests__/enforce-statement-order.test.js +0 -473
  214. package/typescript/copy-overwrite/eslint-plugin-code-organization/index.js +0 -28
  215. package/typescript/copy-overwrite/eslint-plugin-code-organization/package.json +0 -10
  216. package/typescript/copy-overwrite/eslint-plugin-code-organization/rules/enforce-statement-order.js +0 -162
@@ -1,238 +0,0 @@
1
- ---
2
- name: apollo-client
3
- description: This skill should be used when writing or modifying GraphQL operations, hooks, or mutations using Apollo Client 3.10. It enforces best practices for optimistic responses, cache updates, and TypeScript type generation. Use this skill when creating new queries/mutations, reviewing Apollo code, or troubleshooting cache issues.
4
- ---
5
-
6
- # Apollo Client 3.10
7
-
8
- ## Overview
9
-
10
- This skill provides best practices for Apollo Client 3.10 in this codebase, ensuring consistent patterns for GraphQL operations, optimistic UI updates, cache management, and TypeScript type safety.
11
-
12
- ## Quick Reference
13
-
14
- ### Generator Commands
15
-
16
- After modifying any `operations.graphql` file, run the appropriate generator:
17
-
18
- ```bash
19
- bun run generate:types:dev # Development environment
20
- bun run generate:types:staging # Staging environment
21
- bun run generate:types:production # Production environment
22
- ```
23
-
24
- > **Note:** Replace `bun` with your project's package manager (`npm`, `yarn`, `pnpm`) as needed.
25
-
26
- ### Import Pattern
27
-
28
- All GraphQL types, hooks, and documents must come from generated types:
29
-
30
- ```typescript
31
- import {
32
- useGetPlayerQuery,
33
- useUpdatePlayerMutation,
34
- GetPlayerQuery,
35
- PlayerFragment,
36
- ListPlayersDocument,
37
- } from "@/generated/graphql";
38
- ```
39
-
40
- ## Core Rules
41
-
42
- ### 1. Only Use Generated Types
43
-
44
- Import all GraphQL-related types from `@/generated/graphql`. Never define manual TypeScript types for GraphQL entities.
45
-
46
- ```typescript
47
- // CORRECT
48
- import { PlayerFragment, useUpdatePlayerMutation } from "@/generated/graphql";
49
-
50
- // INCORRECT - Never do this
51
- type Player = { id: string; name: string };
52
- ```
53
-
54
- ### 2. Never Modify Generated Files
55
-
56
- The `generated/graphql.ts` file is auto-generated by codegen. To change types:
57
-
58
- 1. Edit the appropriate `operations.graphql` file in the feature directory
59
- 2. Run `bun run generate:types:dev`
60
- 3. Import the newly generated types
61
-
62
- ### 3. Always Run Generator After Schema Changes
63
-
64
- After modifying any `operations.graphql` file, immediately run the generator before committing. Verify changes compile with `bun run typecheck`.
65
-
66
- ### 4. Always Include Optimistic Response
67
-
68
- Every mutation must include an `optimisticResponse` for instant UI feedback:
69
-
70
- ```typescript
71
- const [updatePlayer] = useUpdatePlayerMutation({
72
- optimisticResponse: variables => ({
73
- __typename: "Mutation",
74
- updatePlayer: {
75
- __typename: "Player",
76
- id: variables.id,
77
- name: variables.input.name,
78
- updatedAt: new Date().toISOString(),
79
- },
80
- }),
81
- });
82
- ```
83
-
84
- Key requirements:
85
-
86
- - Always include `__typename` for every object in the response
87
- - Always include `id` for cache normalization
88
- - Use temporary IDs for new objects (e.g., `crypto.randomUUID()`)
89
- - Include all fields that the mutation returns
90
-
91
- ### 5. Always Update Cache
92
-
93
- Every mutation must handle cache updates using one of these strategies:
94
-
95
- **Automatic Updates** - When mutation returns the full entity with `id` and `__typename`, Apollo updates automatically. No extra code needed.
96
-
97
- **cache.modify** - For adding/removing items from lists:
98
-
99
- ```typescript
100
- const [addPlayer] = useAddPlayerMutation({
101
- optimisticResponse: {
102
- /* ... */
103
- },
104
- update(cache, { data }) {
105
- cache.modify({
106
- fields: {
107
- players(existingPlayers = [], { readField }) {
108
- const newRef = cache.writeFragment({
109
- data: data.addPlayer,
110
- fragment: PlayerFragmentDoc,
111
- });
112
- return [...existingPlayers, newRef];
113
- },
114
- },
115
- });
116
- },
117
- });
118
- ```
119
-
120
- **refetchQueries** - Fallback for complex scenarios:
121
-
122
- ```typescript
123
- const [complexMutation] = useComplexMutation({
124
- refetchQueries: ["ListPlayers"],
125
- awaitRefetchQueries: true,
126
- });
127
- ```
128
-
129
- ## Operations.graphql Structure
130
-
131
- ### Fragment-First Pattern
132
-
133
- Define fragments before queries/mutations that use them:
134
-
135
- ```graphql
136
- # 1. Fragments first
137
- fragment PlayerFragment on Player {
138
- id
139
- knownName
140
- firstName
141
- lastName
142
- team {
143
- id
144
- name
145
- }
146
- }
147
-
148
- # 2. Queries second
149
- query GetPlayer($id: ID!) {
150
- player(id: $id) {
151
- ...PlayerFragment
152
- }
153
- }
154
-
155
- # 3. Mutations last
156
- mutation UpdatePlayer($id: ID!, $input: UpdatePlayerInput!) {
157
- updatePlayer(id: $id, input: $input) {
158
- ...PlayerFragment
159
- }
160
- }
161
- ```
162
-
163
- ### Include Required Fields
164
-
165
- Mutations must return all fields needed for cache updates:
166
-
167
- ```graphql
168
- mutation AddPlayerToKanban($input: AddPlayerToKanbanInput!) {
169
- addPlayerToKanban(input: $input) {
170
- id # Required for cache normalization
171
- position
172
- notes
173
- kanbanPhaseId
174
- kanbanPhase {
175
- # Include related objects
176
- id
177
- name
178
- }
179
- createdAt
180
- updatedAt
181
- }
182
- }
183
- ```
184
-
185
- ## Query Best Practices
186
-
187
- ### Fetch Policies
188
-
189
- ```typescript
190
- // Frequently changing data - balance speed and freshness
191
- fetchPolicy: "cache-and-network";
192
-
193
- // Stable reference data - prioritize cache
194
- fetchPolicy: "cache-first";
195
-
196
- // Always-fresh data - skip cache
197
- fetchPolicy: "network-only";
198
- ```
199
-
200
- ### Skip When Variables Undefined
201
-
202
- ```typescript
203
- const { data } = useGetPlayerQuery({
204
- variables: { id: playerId! },
205
- skip: !playerId,
206
- });
207
- ```
208
-
209
- ### Error Handling
210
-
211
- Use `onError` callback instead of try/catch with console.log:
212
-
213
- ```typescript
214
- const [mutation] = useMutation(MUTATION, {
215
- onError: error => {
216
- setErrorState("Failed to update. Please try again.");
217
- },
218
- });
219
- ```
220
-
221
- ## Complete Mutation Pattern
222
-
223
- Reference `references/mutation-patterns.md` for comprehensive examples of the complete mutation pattern including optimistic responses, cache updates, and error handling.
224
-
225
- ## Validation Checklist
226
-
227
- When writing or reviewing Apollo code, verify:
228
-
229
- - [ ] All types imported from `@/generated/graphql`
230
- - [ ] No manual type definitions for GraphQL entities
231
- - [ ] Every mutation has `optimisticResponse`
232
- - [ ] Every mutation has cache update strategy
233
- - [ ] `__typename` included in all optimistic response objects
234
- - [ ] `id` included in all optimistic response objects
235
- - [ ] Queries use appropriate `fetchPolicy`
236
- - [ ] Queries use `skip` when variables may be undefined
237
- - [ ] Error handling via `onError` callback
238
- - [ ] Generator was run after operations.graphql changes
@@ -1,360 +0,0 @@
1
- # Apollo Client Mutation Patterns
2
-
3
- This reference provides comprehensive examples of mutation patterns for Apollo Client 3.10.
4
-
5
- ## Complete Mutation Hook Pattern
6
-
7
- Every custom mutation hook should follow this structure:
8
-
9
- ```typescript
10
- import { useCallback } from "react";
11
- import {
12
- useUpdateKanbanCardMutation,
13
- KanbanCardFragment,
14
- KanbanCardFragmentDoc,
15
- } from "@/generated/graphql";
16
-
17
- /**
18
- * Hook for updating kanban card with optimistic UI
19
- * @param boardId - The board ID for context
20
- * @returns Object containing update function and loading state
21
- */
22
- export const useUpdateCard = (boardId: string) => {
23
- const [updateCardMutation, { loading }] = useUpdateKanbanCardMutation({
24
- // 1. OPTIMISTIC RESPONSE - Provides instant UI feedback
25
- optimisticResponse: variables => ({
26
- __typename: "Mutation",
27
- updateKanbanCard: {
28
- __typename: "KanbanCard",
29
- id: variables.id,
30
- notes: variables.input.notes ?? null,
31
- position: variables.input.position ?? 0,
32
- kanbanPhaseId: variables.input.kanbanPhaseId ?? "",
33
- kanbanPhase: {
34
- __typename: "KanbanPhase",
35
- id: variables.input.kanbanPhaseId ?? "",
36
- name: "", // Will be updated by server response
37
- },
38
- createdAt: new Date().toISOString(),
39
- updatedAt: new Date().toISOString(),
40
- },
41
- }),
42
-
43
- // 2. CACHE UPDATE - Ensures UI stays in sync
44
- update(cache, { data }) {
45
- if (!data?.updateKanbanCard) return;
46
-
47
- // For simple field updates, Apollo handles automatically
48
- // For complex scenarios, use cache.modify:
49
- cache.modify({
50
- id: cache.identify({
51
- __typename: "KanbanCard",
52
- id: data.updateKanbanCard.id,
53
- }),
54
- fields: {
55
- notes: () => data.updateKanbanCard.notes,
56
- position: () => data.updateKanbanCard.position,
57
- },
58
- });
59
- },
60
-
61
- // 3. ERROR HANDLING - Never pollutes console
62
- onError: () => {
63
- // Set error state in UI, don't console.log
64
- },
65
- });
66
-
67
- // 4. WRAPPED CALLBACK - Proper memoization
68
- const updateCard = useCallback(
69
- async (cardId: string, notes: string) => {
70
- await updateCardMutation({
71
- variables: {
72
- id: cardId,
73
- input: { notes },
74
- },
75
- });
76
- },
77
- [updateCardMutation]
78
- );
79
-
80
- return { updateCard, isUpdating: loading };
81
- };
82
- ```
83
-
84
- ## Adding Items to a List
85
-
86
- When creating new items that need to appear in a list:
87
-
88
- ```typescript
89
- const [addPlayerMutation] = useAddPlayerToKanbanMutation({
90
- optimisticResponse: variables => ({
91
- __typename: "Mutation",
92
- addPlayerToKanban: {
93
- __typename: "KanbanCard",
94
- id: crypto.randomUUID(), // Temporary ID for new items
95
- position: 0,
96
- notes: variables.input.notes ?? null,
97
- kanbanPhaseId: variables.input.kanbanPhaseId,
98
- kanbanPhase: {
99
- __typename: "KanbanPhase",
100
- id: variables.input.kanbanPhaseId,
101
- name: "", // Will be replaced by server
102
- },
103
- createdAt: new Date().toISOString(),
104
- updatedAt: new Date().toISOString(),
105
- },
106
- }),
107
-
108
- update(cache, { data }) {
109
- if (!data?.addPlayerToKanban) return;
110
-
111
- cache.modify({
112
- fields: {
113
- listKanbanCards(existingCards = { edges: [] }) {
114
- const newCardRef = cache.writeFragment({
115
- data: data.addPlayerToKanban,
116
- fragment: KanbanCardFragmentDoc,
117
- });
118
-
119
- return {
120
- ...existingCards,
121
- edges: [
122
- ...existingCards.edges,
123
- {
124
- __typename: "KanbanCardEdge",
125
- cursor: "",
126
- node: { __ref: newCardRef.__ref },
127
- },
128
- ],
129
- };
130
- },
131
- },
132
- });
133
- },
134
-
135
- onError: () => {
136
- // Handle error in UI state
137
- },
138
- });
139
- ```
140
-
141
- ## Removing Items from a List
142
-
143
- When deleting items that should disappear from a list:
144
-
145
- ```typescript
146
- const [removePlayerMutation] = useRemovePlayerFromKanbanMutation({
147
- optimisticResponse: variables => ({
148
- __typename: "Mutation",
149
- removePlayerFromKanban: {
150
- __typename: "KanbanCard",
151
- id: variables.cardId,
152
- position: 0,
153
- notes: null,
154
- kanbanPhaseId: "",
155
- kanbanPhase: {
156
- __typename: "KanbanPhase",
157
- id: "",
158
- name: "",
159
- },
160
- createdAt: new Date().toISOString(),
161
- updatedAt: new Date().toISOString(),
162
- },
163
- }),
164
-
165
- update(cache, { data }) {
166
- if (!data?.removePlayerFromKanban) return;
167
-
168
- const removedId = data.removePlayerFromKanban.id;
169
-
170
- cache.modify({
171
- fields: {
172
- listKanbanCards(existingCards = { edges: [] }, { readField }) {
173
- return {
174
- ...existingCards,
175
- edges: existingCards.edges.filter(
176
- (edge: { node: { __ref: string } }) => {
177
- const cardRef = edge.node.__ref;
178
- return readField("id", { __ref: cardRef }) !== removedId;
179
- }
180
- ),
181
- };
182
- },
183
- },
184
- });
185
-
186
- // Evict the removed item from cache entirely
187
- cache.evict({
188
- id: cache.identify({
189
- __typename: "KanbanCard",
190
- id: removedId,
191
- }),
192
- });
193
- cache.gc();
194
- },
195
-
196
- onError: () => {
197
- // Handle error in UI state
198
- },
199
- });
200
- ```
201
-
202
- ## Moving Items Between Lists
203
-
204
- When an item moves from one parent to another:
205
-
206
- ```typescript
207
- const [moveCardMutation] = useMoveKanbanCardMutation({
208
- optimisticResponse: variables => ({
209
- __typename: "Mutation",
210
- moveKanbanCard: {
211
- __typename: "KanbanCard",
212
- id: variables.input.cardId,
213
- position: variables.input.targetPosition,
214
- notes: null, // Preserve from existing cache
215
- kanbanPhaseId: variables.input.targetPhaseId,
216
- kanbanPhase: {
217
- __typename: "KanbanPhase",
218
- id: variables.input.targetPhaseId,
219
- name: "", // Will be updated by server
220
- },
221
- createdAt: new Date().toISOString(),
222
- updatedAt: new Date().toISOString(),
223
- },
224
- }),
225
-
226
- // For moves, refetchQueries is often cleaner than manual cache updates
227
- refetchQueries: ["ListKanbanCards"],
228
- awaitRefetchQueries: false, // Don't block UI
229
-
230
- onError: () => {
231
- // Handle error in UI state
232
- },
233
- });
234
- ```
235
-
236
- ## Batch Updates with Reordering
237
-
238
- When updating positions of multiple items:
239
-
240
- ```typescript
241
- const [updatePositionsMutation] = useUpdateKanbanPhasePositionsMutation({
242
- optimisticResponse: variables => ({
243
- __typename: "Mutation",
244
- updateKanbanPhasePositions: variables.input.phasePositions.map(pp => ({
245
- __typename: "KanbanPhase",
246
- id: pp.phaseId,
247
- position: pp.position,
248
- name: "", // Preserve from cache
249
- kanbanBoardId: variables.input.kanbanBoardId,
250
- createdAt: new Date().toISOString(),
251
- updatedAt: new Date().toISOString(),
252
- })),
253
- }),
254
-
255
- refetchQueries: ["ListKanbanPhases"],
256
- awaitRefetchQueries: false,
257
-
258
- onError: () => {
259
- // Handle error in UI state
260
- },
261
- });
262
- ```
263
-
264
- ## Conditional Optimistic Updates
265
-
266
- Skip optimistic updates when conditions aren't met:
267
-
268
- ```typescript
269
- const [updateMutation] = useUpdateMutation({
270
- optimisticResponse: (variables, { IGNORE }) => {
271
- // Skip optimistic update if we don't have enough data
272
- if (!variables.input.name) {
273
- return IGNORE;
274
- }
275
-
276
- return {
277
- __typename: "Mutation",
278
- update: {
279
- __typename: "Entity",
280
- id: variables.id,
281
- name: variables.input.name,
282
- updatedAt: new Date().toISOString(),
283
- },
284
- };
285
- },
286
- });
287
- ```
288
-
289
- ## Cache Update with cache.identify
290
-
291
- Use `cache.identify` to get the correct cache key:
292
-
293
- ```typescript
294
- update(cache, { data }) {
295
- if (!data?.updatePlayer) return;
296
-
297
- const cacheId = cache.identify({
298
- __typename: "Player",
299
- id: data.updatePlayer.id,
300
- });
301
- // cacheId = "Player:abc-123"
302
-
303
- cache.modify({
304
- id: cacheId,
305
- fields: {
306
- isActive: () => true,
307
- updatedAt: () => new Date().toISOString(),
308
- },
309
- });
310
- }
311
- ```
312
-
313
- ## Using readonly Types for Cache Modifiers
314
-
315
- Apollo cache data is readonly. Use proper typing:
316
-
317
- ```typescript
318
- cache.modify({
319
- fields: {
320
- players(existingPlayers: readonly { __ref: string }[] = [], { readField }) {
321
- return existingPlayers.filter(ref => readField("id", ref) !== removedId);
322
- },
323
- },
324
- });
325
- ```
326
-
327
- ## Decision Tree: Cache Update Strategy
328
-
329
- ```
330
- Mutation creates/updates/deletes entity
331
-
332
-
333
- ┌───────────────────────────────┐
334
- │ Does mutation return entity │
335
- │ with id and __typename? │
336
- └───────────────────────────────┘
337
-
338
- ┌──────┴──────┐
339
- │ YES │ NO
340
- ▼ ▼
341
- ┌─────────┐ ┌─────────────────┐
342
- │Automatic│ │ Use │
343
- │ Update │ │ refetchQueries │
344
- └─────────┘ └─────────────────┘
345
-
346
-
347
- ┌───────────────────────────────┐
348
- │ Does entity need to appear │
349
- │ in or disappear from a list? │
350
- └───────────────────────────────┘
351
-
352
- ┌──────┴──────┐
353
- │ YES │ NO
354
- ▼ ▼
355
- ┌─────────────┐ ┌─────────────┐
356
- │cache.modify │ │ Automatic │
357
- │ with list │ │ is enough │
358
- │ manipulation│ │ │
359
- └─────────────┘ └─────────────┘
360
- ```