autoworkflow 3.1.5 → 3.6.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 (124) hide show
  1. package/.claude/commands/analyze.md +19 -0
  2. package/.claude/commands/audit.md +26 -0
  3. package/.claude/commands/build.md +39 -0
  4. package/.claude/commands/commit.md +25 -0
  5. package/.claude/commands/fix.md +23 -0
  6. package/.claude/commands/plan.md +18 -0
  7. package/.claude/commands/suggest.md +23 -0
  8. package/.claude/commands/verify.md +18 -0
  9. package/.claude/hooks/post-bash-router.sh +20 -0
  10. package/.claude/hooks/post-commit.sh +140 -0
  11. package/.claude/hooks/post-edit.sh +190 -17
  12. package/.claude/hooks/pre-edit.sh +221 -0
  13. package/.claude/hooks/session-check.sh +90 -0
  14. package/.claude/settings.json +56 -6
  15. package/.claude/settings.local.json +5 -1
  16. package/.claude/skills/actix.md +337 -0
  17. package/.claude/skills/alembic.md +504 -0
  18. package/.claude/skills/angular.md +237 -0
  19. package/.claude/skills/api-design.md +187 -0
  20. package/.claude/skills/aspnet-core.md +377 -0
  21. package/.claude/skills/astro.md +245 -0
  22. package/.claude/skills/auth-clerk.md +327 -0
  23. package/.claude/skills/auth-firebase.md +367 -0
  24. package/.claude/skills/auth-nextauth.md +359 -0
  25. package/.claude/skills/auth-supabase.md +368 -0
  26. package/.claude/skills/axum.md +386 -0
  27. package/.claude/skills/blazor.md +456 -0
  28. package/.claude/skills/chi.md +348 -0
  29. package/.claude/skills/code-review.md +133 -0
  30. package/.claude/skills/csharp.md +296 -0
  31. package/.claude/skills/css-modules.md +325 -0
  32. package/.claude/skills/cypress.md +343 -0
  33. package/.claude/skills/debugging.md +133 -0
  34. package/.claude/skills/diesel.md +392 -0
  35. package/.claude/skills/django.md +301 -0
  36. package/.claude/skills/docker.md +319 -0
  37. package/.claude/skills/doctrine.md +473 -0
  38. package/.claude/skills/documentation.md +182 -0
  39. package/.claude/skills/dotnet.md +409 -0
  40. package/.claude/skills/drizzle.md +293 -0
  41. package/.claude/skills/echo.md +321 -0
  42. package/.claude/skills/eloquent.md +256 -0
  43. package/.claude/skills/emotion.md +426 -0
  44. package/.claude/skills/entity-framework.md +370 -0
  45. package/.claude/skills/express.md +316 -0
  46. package/.claude/skills/fastapi.md +329 -0
  47. package/.claude/skills/fastify.md +299 -0
  48. package/.claude/skills/fiber.md +315 -0
  49. package/.claude/skills/flask.md +322 -0
  50. package/.claude/skills/gin.md +342 -0
  51. package/.claude/skills/git.md +116 -0
  52. package/.claude/skills/github-actions.md +353 -0
  53. package/.claude/skills/go.md +377 -0
  54. package/.claude/skills/gorm.md +409 -0
  55. package/.claude/skills/graphql.md +478 -0
  56. package/.claude/skills/hibernate.md +379 -0
  57. package/.claude/skills/hono.md +306 -0
  58. package/.claude/skills/java.md +400 -0
  59. package/.claude/skills/jest.md +313 -0
  60. package/.claude/skills/jpa.md +282 -0
  61. package/.claude/skills/kotlin.md +347 -0
  62. package/.claude/skills/kubernetes.md +363 -0
  63. package/.claude/skills/laravel.md +414 -0
  64. package/.claude/skills/mcp-browser.md +320 -0
  65. package/.claude/skills/mcp-database.md +219 -0
  66. package/.claude/skills/mcp-fetch.md +241 -0
  67. package/.claude/skills/mcp-filesystem.md +204 -0
  68. package/.claude/skills/mcp-github.md +217 -0
  69. package/.claude/skills/mcp-memory.md +240 -0
  70. package/.claude/skills/mcp-search.md +218 -0
  71. package/.claude/skills/mcp-slack.md +262 -0
  72. package/.claude/skills/micronaut.md +388 -0
  73. package/.claude/skills/mongodb.md +319 -0
  74. package/.claude/skills/mongoose.md +355 -0
  75. package/.claude/skills/mysql.md +281 -0
  76. package/.claude/skills/nestjs.md +335 -0
  77. package/.claude/skills/nextjs-app-router.md +260 -0
  78. package/.claude/skills/nextjs-pages.md +172 -0
  79. package/.claude/skills/nuxt.md +202 -0
  80. package/.claude/skills/openapi.md +489 -0
  81. package/.claude/skills/performance.md +199 -0
  82. package/.claude/skills/php.md +398 -0
  83. package/.claude/skills/playwright.md +371 -0
  84. package/.claude/skills/postgresql.md +257 -0
  85. package/.claude/skills/prisma.md +293 -0
  86. package/.claude/skills/pydantic.md +304 -0
  87. package/.claude/skills/pytest.md +313 -0
  88. package/.claude/skills/python.md +272 -0
  89. package/.claude/skills/quarkus.md +377 -0
  90. package/.claude/skills/react.md +230 -0
  91. package/.claude/skills/redis.md +391 -0
  92. package/.claude/skills/refactoring.md +143 -0
  93. package/.claude/skills/remix.md +246 -0
  94. package/.claude/skills/rest-api.md +490 -0
  95. package/.claude/skills/rocket.md +366 -0
  96. package/.claude/skills/rust.md +341 -0
  97. package/.claude/skills/sass.md +380 -0
  98. package/.claude/skills/sea-orm.md +382 -0
  99. package/.claude/skills/security.md +167 -0
  100. package/.claude/skills/sequelize.md +395 -0
  101. package/.claude/skills/spring-boot.md +416 -0
  102. package/.claude/skills/sqlalchemy.md +269 -0
  103. package/.claude/skills/sqlx-rust.md +408 -0
  104. package/.claude/skills/state-jotai.md +346 -0
  105. package/.claude/skills/state-mobx.md +353 -0
  106. package/.claude/skills/state-pinia.md +431 -0
  107. package/.claude/skills/state-redux.md +337 -0
  108. package/.claude/skills/state-tanstack-query.md +434 -0
  109. package/.claude/skills/state-zustand.md +340 -0
  110. package/.claude/skills/styled-components.md +403 -0
  111. package/.claude/skills/svelte.md +238 -0
  112. package/.claude/skills/sveltekit.md +207 -0
  113. package/.claude/skills/symfony.md +437 -0
  114. package/.claude/skills/tailwind.md +279 -0
  115. package/.claude/skills/terraform.md +394 -0
  116. package/.claude/skills/testing-library.md +371 -0
  117. package/.claude/skills/trpc.md +426 -0
  118. package/.claude/skills/typeorm.md +368 -0
  119. package/.claude/skills/vitest.md +330 -0
  120. package/.claude/skills/vue.md +202 -0
  121. package/.claude/skills/warp.md +365 -0
  122. package/README.md +163 -52
  123. package/package.json +1 -1
  124. package/system/triggers.md +256 -17
@@ -0,0 +1,340 @@
1
+ # Zustand Skill
2
+
3
+ ## Basic Store
4
+ \`\`\`typescript
5
+ import { create } from 'zustand';
6
+
7
+ interface User {
8
+ id: string;
9
+ email: string;
10
+ name: string;
11
+ }
12
+
13
+ interface UserStore {
14
+ // State
15
+ user: User | null;
16
+ loading: boolean;
17
+ error: string | null;
18
+
19
+ // Actions
20
+ setUser: (user: User) => void;
21
+ clearUser: () => void;
22
+ fetchUser: (id: string) => Promise<void>;
23
+ }
24
+
25
+ const useUserStore = create<UserStore>((set, get) => ({
26
+ // Initial state
27
+ user: null,
28
+ loading: false,
29
+ error: null,
30
+
31
+ // Sync actions
32
+ setUser: (user) => set({ user }),
33
+ clearUser: () => set({ user: null, error: null }),
34
+
35
+ // Async action
36
+ fetchUser: async (id) => {
37
+ set({ loading: true, error: null });
38
+ try {
39
+ const response = await fetch(\`/api/users/\${id}\`);
40
+ if (!response.ok) throw new Error('Failed to fetch user');
41
+ const user = await response.json();
42
+ set({ user, loading: false });
43
+ } catch (error) {
44
+ set({ error: (error as Error).message, loading: false });
45
+ }
46
+ },
47
+ }));
48
+
49
+ // Usage in components
50
+ function UserProfile({ userId }: { userId: string }) {
51
+ const { user, loading, fetchUser } = useUserStore();
52
+
53
+ useEffect(() => {
54
+ fetchUser(userId);
55
+ }, [userId, fetchUser]);
56
+
57
+ if (loading) return <div>Loading...</div>;
58
+ return <div>{user?.name}</div>;
59
+ }
60
+ \`\`\`
61
+
62
+ ## Selectors (Performance Optimization)
63
+ \`\`\`typescript
64
+ // ❌ Bad: Re-renders on any state change
65
+ const { user, loading, error } = useUserStore();
66
+
67
+ // ✅ Good: Only re-renders when selected state changes
68
+ const user = useUserStore((state) => state.user);
69
+ const loading = useUserStore((state) => state.loading);
70
+
71
+ // Multiple values with shallow comparison
72
+ import { shallow } from 'zustand/shallow';
73
+
74
+ const { user, loading } = useUserStore(
75
+ (state) => ({ user: state.user, loading: state.loading }),
76
+ shallow
77
+ );
78
+
79
+ // Or use useShallow hook
80
+ import { useShallow } from 'zustand/react/shallow';
81
+
82
+ const { user, loading } = useUserStore(
83
+ useShallow((state) => ({ user: state.user, loading: state.loading }))
84
+ );
85
+
86
+ // Derived/computed values
87
+ const userName = useUserStore((state) => state.user?.name);
88
+ const isLoggedIn = useUserStore((state) => !!state.user);
89
+ \`\`\`
90
+
91
+ ## Slices Pattern (Multiple Stores)
92
+ \`\`\`typescript
93
+ import { create, StateCreator } from 'zustand';
94
+
95
+ // User slice
96
+ interface UserSlice {
97
+ user: User | null;
98
+ setUser: (user: User) => void;
99
+ logout: () => void;
100
+ }
101
+
102
+ const createUserSlice: StateCreator<
103
+ UserSlice & CartSlice,
104
+ [],
105
+ [],
106
+ UserSlice
107
+ > = (set) => ({
108
+ user: null,
109
+ setUser: (user) => set({ user }),
110
+ logout: () => set({ user: null }),
111
+ });
112
+
113
+ // Cart slice
114
+ interface CartSlice {
115
+ items: CartItem[];
116
+ addItem: (item: CartItem) => void;
117
+ removeItem: (id: string) => void;
118
+ clearCart: () => void;
119
+ }
120
+
121
+ const createCartSlice: StateCreator<
122
+ UserSlice & CartSlice,
123
+ [],
124
+ [],
125
+ CartSlice
126
+ > = (set) => ({
127
+ items: [],
128
+ addItem: (item) => set((state) => ({ items: [...state.items, item] })),
129
+ removeItem: (id) => set((state) => ({
130
+ items: state.items.filter((item) => item.id !== id),
131
+ })),
132
+ clearCart: () => set({ items: [] }),
133
+ });
134
+
135
+ // Combined store
136
+ type StoreState = UserSlice & CartSlice;
137
+
138
+ const useStore = create<StoreState>()((...a) => ({
139
+ ...createUserSlice(...a),
140
+ ...createCartSlice(...a),
141
+ }));
142
+
143
+ // Usage
144
+ const user = useStore((state) => state.user);
145
+ const items = useStore((state) => state.items);
146
+ \`\`\`
147
+
148
+ ## Middleware
149
+
150
+ ### Persist (localStorage/sessionStorage)
151
+ \`\`\`typescript
152
+ import { create } from 'zustand';
153
+ import { persist, createJSONStorage } from 'zustand/middleware';
154
+
155
+ const useUserStore = create<UserStore>()(
156
+ persist(
157
+ (set, get) => ({
158
+ user: null,
159
+ setUser: (user) => set({ user }),
160
+ logout: () => set({ user: null }),
161
+ }),
162
+ {
163
+ name: 'user-storage', // localStorage key
164
+ storage: createJSONStorage(() => localStorage), // default
165
+ // Or sessionStorage:
166
+ // storage: createJSONStorage(() => sessionStorage),
167
+
168
+ // Partial persistence (only persist some fields)
169
+ partialize: (state) => ({ user: state.user }),
170
+
171
+ // Version for migrations
172
+ version: 1,
173
+ migrate: (persistedState, version) => {
174
+ if (version === 0) {
175
+ // Migration logic
176
+ }
177
+ return persistedState as UserStore;
178
+ },
179
+
180
+ // Skip hydration until ready
181
+ skipHydration: true,
182
+ }
183
+ )
184
+ );
185
+
186
+ // Manual hydration (when skipHydration: true)
187
+ useEffect(() => {
188
+ useUserStore.persist.rehydrate();
189
+ }, []);
190
+
191
+ // Clear persisted state
192
+ useUserStore.persist.clearStorage();
193
+ \`\`\`
194
+
195
+ ### DevTools
196
+ \`\`\`typescript
197
+ import { create } from 'zustand';
198
+ import { devtools } from 'zustand/middleware';
199
+
200
+ const useStore = create<StoreState>()(
201
+ devtools(
202
+ (set) => ({
203
+ // ... store
204
+ }),
205
+ {
206
+ name: 'MyApp Store', // Name in DevTools
207
+ enabled: process.env.NODE_ENV === 'development',
208
+ }
209
+ )
210
+ );
211
+
212
+ // Named actions in DevTools
213
+ set({ user }, false, 'setUser');
214
+ set({ user: null }, false, 'logout');
215
+ \`\`\`
216
+
217
+ ### Immer (Immutable Updates)
218
+ \`\`\`typescript
219
+ import { create } from 'zustand';
220
+ import { immer } from 'zustand/middleware/immer';
221
+
222
+ interface TodoStore {
223
+ todos: Todo[];
224
+ addTodo: (text: string) => void;
225
+ toggleTodo: (id: string) => void;
226
+ updateTodo: (id: string, text: string) => void;
227
+ }
228
+
229
+ const useTodoStore = create<TodoStore>()(
230
+ immer((set) => ({
231
+ todos: [],
232
+
233
+ addTodo: (text) =>
234
+ set((state) => {
235
+ state.todos.push({ id: crypto.randomUUID(), text, completed: false });
236
+ }),
237
+
238
+ toggleTodo: (id) =>
239
+ set((state) => {
240
+ const todo = state.todos.find((t) => t.id === id);
241
+ if (todo) todo.completed = !todo.completed;
242
+ }),
243
+
244
+ updateTodo: (id, text) =>
245
+ set((state) => {
246
+ const todo = state.todos.find((t) => t.id === id);
247
+ if (todo) todo.text = text;
248
+ }),
249
+ }))
250
+ );
251
+ \`\`\`
252
+
253
+ ### Combining Middleware
254
+ \`\`\`typescript
255
+ const useStore = create<StoreState>()(
256
+ devtools(
257
+ persist(
258
+ immer((set) => ({
259
+ // ... store implementation
260
+ })),
261
+ { name: 'app-storage' }
262
+ ),
263
+ { name: 'AppStore' }
264
+ )
265
+ );
266
+ \`\`\`
267
+
268
+ ## Subscribing to Changes
269
+ \`\`\`typescript
270
+ // Subscribe outside React
271
+ const unsubscribe = useUserStore.subscribe(
272
+ (state) => console.log('State changed:', state)
273
+ );
274
+
275
+ // Subscribe to specific slice
276
+ const unsubscribe = useUserStore.subscribe(
277
+ (state) => state.user,
278
+ (user, prevUser) => {
279
+ console.log('User changed:', { user, prevUser });
280
+ }
281
+ );
282
+
283
+ // Get state outside React
284
+ const currentUser = useUserStore.getState().user;
285
+
286
+ // Set state outside React
287
+ useUserStore.setState({ user: newUser });
288
+
289
+ // With action
290
+ useUserStore.getState().setUser(newUser);
291
+ \`\`\`
292
+
293
+ ## Testing
294
+ \`\`\`typescript
295
+ import { act, renderHook } from '@testing-library/react';
296
+ import { useUserStore } from './userStore';
297
+
298
+ // Reset store between tests
299
+ beforeEach(() => {
300
+ useUserStore.setState({ user: null, loading: false, error: null });
301
+ });
302
+
303
+ test('should set user', () => {
304
+ const { result } = renderHook(() => useUserStore());
305
+
306
+ act(() => {
307
+ result.current.setUser({ id: '1', email: 'test@example.com', name: 'Test' });
308
+ });
309
+
310
+ expect(result.current.user).toEqual({
311
+ id: '1',
312
+ email: 'test@example.com',
313
+ name: 'Test',
314
+ });
315
+ });
316
+
317
+ // Test with initial state
318
+ test('should start with loading false', () => {
319
+ const { result } = renderHook(() =>
320
+ useUserStore((state) => state.loading)
321
+ );
322
+
323
+ expect(result.current).toBe(false);
324
+ });
325
+ \`\`\`
326
+
327
+ ## ❌ DON'T
328
+ - Destructure entire store (causes unnecessary re-renders)
329
+ - Put functions in state that should be actions
330
+ - Forget to use shallow comparison for object selectors
331
+ - Mutate state directly (use set or immer)
332
+
333
+ ## ✅ DO
334
+ - Use selectors for fine-grained subscriptions
335
+ - Use shallow for multiple values
336
+ - Use persist middleware for local storage
337
+ - Use devtools in development
338
+ - Use immer for complex nested updates
339
+ - Use slices for large stores
340
+ - Reset store state in tests