autoworkflow 3.1.5 → 3.5.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 (123) 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/pre-edit.sh +129 -0
  12. package/.claude/hooks/session-check.sh +79 -0
  13. package/.claude/settings.json +40 -6
  14. package/.claude/settings.local.json +3 -1
  15. package/.claude/skills/actix.md +337 -0
  16. package/.claude/skills/alembic.md +504 -0
  17. package/.claude/skills/angular.md +237 -0
  18. package/.claude/skills/api-design.md +187 -0
  19. package/.claude/skills/aspnet-core.md +377 -0
  20. package/.claude/skills/astro.md +245 -0
  21. package/.claude/skills/auth-clerk.md +327 -0
  22. package/.claude/skills/auth-firebase.md +367 -0
  23. package/.claude/skills/auth-nextauth.md +359 -0
  24. package/.claude/skills/auth-supabase.md +368 -0
  25. package/.claude/skills/axum.md +386 -0
  26. package/.claude/skills/blazor.md +456 -0
  27. package/.claude/skills/chi.md +348 -0
  28. package/.claude/skills/code-review.md +133 -0
  29. package/.claude/skills/csharp.md +296 -0
  30. package/.claude/skills/css-modules.md +325 -0
  31. package/.claude/skills/cypress.md +343 -0
  32. package/.claude/skills/debugging.md +133 -0
  33. package/.claude/skills/diesel.md +392 -0
  34. package/.claude/skills/django.md +301 -0
  35. package/.claude/skills/docker.md +319 -0
  36. package/.claude/skills/doctrine.md +473 -0
  37. package/.claude/skills/documentation.md +182 -0
  38. package/.claude/skills/dotnet.md +409 -0
  39. package/.claude/skills/drizzle.md +293 -0
  40. package/.claude/skills/echo.md +321 -0
  41. package/.claude/skills/eloquent.md +256 -0
  42. package/.claude/skills/emotion.md +426 -0
  43. package/.claude/skills/entity-framework.md +370 -0
  44. package/.claude/skills/express.md +316 -0
  45. package/.claude/skills/fastapi.md +329 -0
  46. package/.claude/skills/fastify.md +299 -0
  47. package/.claude/skills/fiber.md +315 -0
  48. package/.claude/skills/flask.md +322 -0
  49. package/.claude/skills/gin.md +342 -0
  50. package/.claude/skills/git.md +116 -0
  51. package/.claude/skills/github-actions.md +353 -0
  52. package/.claude/skills/go.md +377 -0
  53. package/.claude/skills/gorm.md +409 -0
  54. package/.claude/skills/graphql.md +478 -0
  55. package/.claude/skills/hibernate.md +379 -0
  56. package/.claude/skills/hono.md +306 -0
  57. package/.claude/skills/java.md +400 -0
  58. package/.claude/skills/jest.md +313 -0
  59. package/.claude/skills/jpa.md +282 -0
  60. package/.claude/skills/kotlin.md +347 -0
  61. package/.claude/skills/kubernetes.md +363 -0
  62. package/.claude/skills/laravel.md +414 -0
  63. package/.claude/skills/mcp-browser.md +320 -0
  64. package/.claude/skills/mcp-database.md +219 -0
  65. package/.claude/skills/mcp-fetch.md +241 -0
  66. package/.claude/skills/mcp-filesystem.md +204 -0
  67. package/.claude/skills/mcp-github.md +217 -0
  68. package/.claude/skills/mcp-memory.md +240 -0
  69. package/.claude/skills/mcp-search.md +218 -0
  70. package/.claude/skills/mcp-slack.md +262 -0
  71. package/.claude/skills/micronaut.md +388 -0
  72. package/.claude/skills/mongodb.md +319 -0
  73. package/.claude/skills/mongoose.md +355 -0
  74. package/.claude/skills/mysql.md +281 -0
  75. package/.claude/skills/nestjs.md +335 -0
  76. package/.claude/skills/nextjs-app-router.md +260 -0
  77. package/.claude/skills/nextjs-pages.md +172 -0
  78. package/.claude/skills/nuxt.md +202 -0
  79. package/.claude/skills/openapi.md +489 -0
  80. package/.claude/skills/performance.md +199 -0
  81. package/.claude/skills/php.md +398 -0
  82. package/.claude/skills/playwright.md +371 -0
  83. package/.claude/skills/postgresql.md +257 -0
  84. package/.claude/skills/prisma.md +293 -0
  85. package/.claude/skills/pydantic.md +304 -0
  86. package/.claude/skills/pytest.md +313 -0
  87. package/.claude/skills/python.md +272 -0
  88. package/.claude/skills/quarkus.md +377 -0
  89. package/.claude/skills/react.md +230 -0
  90. package/.claude/skills/redis.md +391 -0
  91. package/.claude/skills/refactoring.md +143 -0
  92. package/.claude/skills/remix.md +246 -0
  93. package/.claude/skills/rest-api.md +490 -0
  94. package/.claude/skills/rocket.md +366 -0
  95. package/.claude/skills/rust.md +341 -0
  96. package/.claude/skills/sass.md +380 -0
  97. package/.claude/skills/sea-orm.md +382 -0
  98. package/.claude/skills/security.md +167 -0
  99. package/.claude/skills/sequelize.md +395 -0
  100. package/.claude/skills/spring-boot.md +416 -0
  101. package/.claude/skills/sqlalchemy.md +269 -0
  102. package/.claude/skills/sqlx-rust.md +408 -0
  103. package/.claude/skills/state-jotai.md +346 -0
  104. package/.claude/skills/state-mobx.md +353 -0
  105. package/.claude/skills/state-pinia.md +431 -0
  106. package/.claude/skills/state-redux.md +337 -0
  107. package/.claude/skills/state-tanstack-query.md +434 -0
  108. package/.claude/skills/state-zustand.md +340 -0
  109. package/.claude/skills/styled-components.md +403 -0
  110. package/.claude/skills/svelte.md +238 -0
  111. package/.claude/skills/sveltekit.md +207 -0
  112. package/.claude/skills/symfony.md +437 -0
  113. package/.claude/skills/tailwind.md +279 -0
  114. package/.claude/skills/terraform.md +394 -0
  115. package/.claude/skills/testing-library.md +371 -0
  116. package/.claude/skills/trpc.md +426 -0
  117. package/.claude/skills/typeorm.md +368 -0
  118. package/.claude/skills/vitest.md +330 -0
  119. package/.claude/skills/vue.md +202 -0
  120. package/.claude/skills/warp.md +365 -0
  121. package/README.md +135 -52
  122. package/package.json +1 -1
  123. package/system/triggers.md +152 -11
@@ -0,0 +1,490 @@
1
+ # REST API Skill
2
+
3
+ ## RESTful Route Design
4
+ \`\`\`
5
+ # Resources use nouns (plural)
6
+ GET /api/users # List users
7
+ GET /api/users/:id # Get single user
8
+ POST /api/users # Create user
9
+ PUT /api/users/:id # Replace user (full update)
10
+ PATCH /api/users/:id # Partial update
11
+ DELETE /api/users/:id # Delete user
12
+
13
+ # Nested resources
14
+ GET /api/users/:id/posts # User's posts
15
+ POST /api/users/:id/posts # Create post for user
16
+ GET /api/posts/:id/comments # Post's comments
17
+
18
+ # Actions (when CRUD doesn't fit)
19
+ POST /api/users/:id/verify # Verify user
20
+ POST /api/posts/:id/publish # Publish post
21
+ POST /api/auth/login # Login
22
+ POST /api/auth/logout # Logout
23
+
24
+ # Filtering, sorting, pagination
25
+ GET /api/users?status=active&role=admin
26
+ GET /api/users?sort=created_at&order=desc
27
+ GET /api/users?page=2&limit=20
28
+ GET /api/users?cursor=abc123&limit=20
29
+ GET /api/posts?search=typescript&tags=react,node
30
+ \`\`\`
31
+
32
+ ## Express.js Implementation
33
+ \`\`\`typescript
34
+ // routes/users.ts
35
+ import { Router } from 'express';
36
+ import { z } from 'zod';
37
+ import { prisma } from '../lib/prisma';
38
+ import { authenticate } from '../middleware/auth';
39
+ import { validate } from '../middleware/validate';
40
+ import { ApiError } from '../lib/errors';
41
+
42
+ const router = Router();
43
+
44
+ // Validation schemas
45
+ const createUserSchema = z.object({
46
+ body: z.object({
47
+ email: z.string().email(),
48
+ name: z.string().min(2).max(100),
49
+ password: z.string().min(8),
50
+ }),
51
+ });
52
+
53
+ const updateUserSchema = z.object({
54
+ body: z.object({
55
+ name: z.string().min(2).max(100).optional(),
56
+ bio: z.string().max(500).optional(),
57
+ }),
58
+ params: z.object({
59
+ id: z.string().uuid(),
60
+ }),
61
+ });
62
+
63
+ const listUsersSchema = z.object({
64
+ query: z.object({
65
+ page: z.coerce.number().min(1).default(1),
66
+ limit: z.coerce.number().min(1).max(100).default(20),
67
+ status: z.enum(['active', 'inactive']).optional(),
68
+ search: z.string().optional(),
69
+ }),
70
+ });
71
+
72
+ // List users with pagination
73
+ router.get('/', validate(listUsersSchema), async (req, res) => {
74
+ const { page, limit, status, search } = req.query;
75
+
76
+ const where = {
77
+ ...(status && { status }),
78
+ ...(search && {
79
+ OR: [
80
+ { name: { contains: search, mode: 'insensitive' } },
81
+ { email: { contains: search, mode: 'insensitive' } },
82
+ ],
83
+ }),
84
+ };
85
+
86
+ const [users, total] = await Promise.all([
87
+ prisma.user.findMany({
88
+ where,
89
+ skip: (page - 1) * limit,
90
+ take: limit,
91
+ orderBy: { createdAt: 'desc' },
92
+ select: {
93
+ id: true,
94
+ name: true,
95
+ email: true,
96
+ createdAt: true,
97
+ },
98
+ }),
99
+ prisma.user.count({ where }),
100
+ ]);
101
+
102
+ res.json({
103
+ data: users,
104
+ meta: {
105
+ page,
106
+ limit,
107
+ total,
108
+ totalPages: Math.ceil(total / limit),
109
+ },
110
+ });
111
+ });
112
+
113
+ // Get single user
114
+ router.get('/:id', async (req, res) => {
115
+ const user = await prisma.user.findUnique({
116
+ where: { id: req.params.id },
117
+ select: {
118
+ id: true,
119
+ name: true,
120
+ email: true,
121
+ bio: true,
122
+ createdAt: true,
123
+ },
124
+ });
125
+
126
+ if (!user) {
127
+ throw new ApiError(404, 'USER_NOT_FOUND', 'User not found');
128
+ }
129
+
130
+ res.json({ data: user });
131
+ });
132
+
133
+ // Create user
134
+ router.post('/', validate(createUserSchema), async (req, res) => {
135
+ const { email, name, password } = req.body;
136
+
137
+ const existing = await prisma.user.findUnique({ where: { email } });
138
+ if (existing) {
139
+ throw new ApiError(409, 'EMAIL_EXISTS', 'Email already registered');
140
+ }
141
+
142
+ const hashedPassword = await bcrypt.hash(password, 12);
143
+ const user = await prisma.user.create({
144
+ data: { email, name, password: hashedPassword },
145
+ select: { id: true, email: true, name: true },
146
+ });
147
+
148
+ res.status(201).json({ data: user });
149
+ });
150
+
151
+ // Update user (partial)
152
+ router.patch('/:id', authenticate, validate(updateUserSchema), async (req, res) => {
153
+ if (req.user.id !== req.params.id && req.user.role !== 'admin') {
154
+ throw new ApiError(403, 'FORBIDDEN', 'Not authorized');
155
+ }
156
+
157
+ const user = await prisma.user.update({
158
+ where: { id: req.params.id },
159
+ data: req.body,
160
+ select: { id: true, name: true, bio: true },
161
+ });
162
+
163
+ res.json({ data: user });
164
+ });
165
+
166
+ // Delete user
167
+ router.delete('/:id', authenticate, async (req, res) => {
168
+ if (req.user.id !== req.params.id && req.user.role !== 'admin') {
169
+ throw new ApiError(403, 'FORBIDDEN', 'Not authorized');
170
+ }
171
+
172
+ await prisma.user.delete({ where: { id: req.params.id } });
173
+ res.status(204).send();
174
+ });
175
+
176
+ export default router;
177
+ \`\`\`
178
+
179
+ ## Next.js App Router API
180
+ \`\`\`typescript
181
+ // app/api/users/route.ts
182
+ import { NextRequest, NextResponse } from 'next/server';
183
+ import { z } from 'zod';
184
+ import { prisma } from '@/lib/prisma';
185
+ import { getSession } from '@/lib/auth';
186
+
187
+ const createUserSchema = z.object({
188
+ email: z.string().email(),
189
+ name: z.string().min(2),
190
+ });
191
+
192
+ // GET /api/users
193
+ export async function GET(request: NextRequest) {
194
+ const { searchParams } = new URL(request.url);
195
+ const page = Number(searchParams.get('page')) || 1;
196
+ const limit = Math.min(Number(searchParams.get('limit')) || 20, 100);
197
+
198
+ const [users, total] = await Promise.all([
199
+ prisma.user.findMany({
200
+ skip: (page - 1) * limit,
201
+ take: limit,
202
+ }),
203
+ prisma.user.count(),
204
+ ]);
205
+
206
+ return NextResponse.json({
207
+ data: users,
208
+ meta: { page, limit, total },
209
+ });
210
+ }
211
+
212
+ // POST /api/users
213
+ export async function POST(request: NextRequest) {
214
+ try {
215
+ const body = await request.json();
216
+ const validated = createUserSchema.parse(body);
217
+
218
+ const user = await prisma.user.create({
219
+ data: validated,
220
+ });
221
+
222
+ return NextResponse.json({ data: user }, { status: 201 });
223
+ } catch (error) {
224
+ if (error instanceof z.ZodError) {
225
+ return NextResponse.json(
226
+ {
227
+ error: {
228
+ code: 'VALIDATION_ERROR',
229
+ message: 'Invalid input',
230
+ details: error.errors,
231
+ },
232
+ },
233
+ { status: 400 }
234
+ );
235
+ }
236
+ throw error;
237
+ }
238
+ }
239
+
240
+ // app/api/users/[id]/route.ts
241
+ export async function GET(
242
+ request: NextRequest,
243
+ { params }: { params: { id: string } }
244
+ ) {
245
+ const user = await prisma.user.findUnique({
246
+ where: { id: params.id },
247
+ });
248
+
249
+ if (!user) {
250
+ return NextResponse.json(
251
+ { error: { code: 'NOT_FOUND', message: 'User not found' } },
252
+ { status: 404 }
253
+ );
254
+ }
255
+
256
+ return NextResponse.json({ data: user });
257
+ }
258
+
259
+ export async function PATCH(
260
+ request: NextRequest,
261
+ { params }: { params: { id: string } }
262
+ ) {
263
+ const session = await getSession();
264
+ if (!session) {
265
+ return NextResponse.json(
266
+ { error: { code: 'UNAUTHORIZED', message: 'Not authenticated' } },
267
+ { status: 401 }
268
+ );
269
+ }
270
+
271
+ const body = await request.json();
272
+ const user = await prisma.user.update({
273
+ where: { id: params.id },
274
+ data: body,
275
+ });
276
+
277
+ return NextResponse.json({ data: user });
278
+ }
279
+
280
+ export async function DELETE(
281
+ request: NextRequest,
282
+ { params }: { params: { id: string } }
283
+ ) {
284
+ await prisma.user.delete({ where: { id: params.id } });
285
+ return new NextResponse(null, { status: 204 });
286
+ }
287
+ \`\`\`
288
+
289
+ ## Middleware
290
+ \`\`\`typescript
291
+ // middleware/auth.ts
292
+ import { Request, Response, NextFunction } from 'express';
293
+ import jwt from 'jsonwebtoken';
294
+ import { ApiError } from '../lib/errors';
295
+
296
+ export async function authenticate(
297
+ req: Request,
298
+ res: Response,
299
+ next: NextFunction
300
+ ) {
301
+ const authHeader = req.headers.authorization;
302
+
303
+ if (!authHeader?.startsWith('Bearer ')) {
304
+ throw new ApiError(401, 'UNAUTHORIZED', 'Missing authentication token');
305
+ }
306
+
307
+ const token = authHeader.split(' ')[1];
308
+
309
+ try {
310
+ const decoded = jwt.verify(token, process.env.JWT_SECRET!);
311
+ req.user = decoded as User;
312
+ next();
313
+ } catch {
314
+ throw new ApiError(401, 'INVALID_TOKEN', 'Invalid or expired token');
315
+ }
316
+ }
317
+
318
+ // middleware/validate.ts
319
+ import { Request, Response, NextFunction } from 'express';
320
+ import { AnyZodObject, ZodError } from 'zod';
321
+
322
+ export function validate(schema: AnyZodObject) {
323
+ return async (req: Request, res: Response, next: NextFunction) => {
324
+ try {
325
+ await schema.parseAsync({
326
+ body: req.body,
327
+ query: req.query,
328
+ params: req.params,
329
+ });
330
+ next();
331
+ } catch (error) {
332
+ if (error instanceof ZodError) {
333
+ res.status(400).json({
334
+ error: {
335
+ code: 'VALIDATION_ERROR',
336
+ message: 'Invalid request data',
337
+ details: error.errors.map((e) => ({
338
+ field: e.path.join('.'),
339
+ message: e.message,
340
+ })),
341
+ },
342
+ });
343
+ } else {
344
+ next(error);
345
+ }
346
+ }
347
+ };
348
+ }
349
+
350
+ // middleware/rateLimit.ts
351
+ import rateLimit from 'express-rate-limit';
352
+
353
+ export const apiLimiter = rateLimit({
354
+ windowMs: 15 * 60 * 1000, // 15 minutes
355
+ max: 100,
356
+ message: {
357
+ error: {
358
+ code: 'TOO_MANY_REQUESTS',
359
+ message: 'Too many requests, please try again later',
360
+ },
361
+ },
362
+ });
363
+ \`\`\`
364
+
365
+ ## Error Handling
366
+ \`\`\`typescript
367
+ // lib/errors.ts
368
+ export class ApiError extends Error {
369
+ constructor(
370
+ public statusCode: number,
371
+ public code: string,
372
+ message: string,
373
+ public details?: unknown
374
+ ) {
375
+ super(message);
376
+ this.name = 'ApiError';
377
+ }
378
+ }
379
+
380
+ // middleware/errorHandler.ts
381
+ import { Request, Response, NextFunction } from 'express';
382
+ import { ApiError } from '../lib/errors';
383
+
384
+ export function errorHandler(
385
+ error: Error,
386
+ req: Request,
387
+ res: Response,
388
+ next: NextFunction
389
+ ) {
390
+ console.error(error);
391
+
392
+ if (error instanceof ApiError) {
393
+ return res.status(error.statusCode).json({
394
+ error: {
395
+ code: error.code,
396
+ message: error.message,
397
+ ...(error.details && { details: error.details }),
398
+ },
399
+ });
400
+ }
401
+
402
+ // Default to 500
403
+ res.status(500).json({
404
+ error: {
405
+ code: 'INTERNAL_ERROR',
406
+ message: 'An unexpected error occurred',
407
+ },
408
+ });
409
+ }
410
+ \`\`\`
411
+
412
+ ## HTTP Status Codes
413
+ \`\`\`
414
+ # Success
415
+ 200 OK - GET, PUT, PATCH success
416
+ 201 Created - POST success (include Location header)
417
+ 204 No Content - DELETE success
418
+
419
+ # Client Errors
420
+ 400 Bad Request - Validation error, malformed request
421
+ 401 Unauthorized - Missing/invalid authentication
422
+ 403 Forbidden - Authenticated but not authorized
423
+ 404 Not Found - Resource doesn't exist
424
+ 409 Conflict - Duplicate resource, state conflict
425
+ 422 Unprocessable - Valid JSON but semantic errors
426
+ 429 Too Many Reqs - Rate limited
427
+
428
+ # Server Errors
429
+ 500 Internal Error - Unexpected server error
430
+ 502 Bad Gateway - Upstream service error
431
+ 503 Unavailable - Temporarily unavailable
432
+ \`\`\`
433
+
434
+ ## Response Formats
435
+ \`\`\`json
436
+ // Success with data
437
+ {
438
+ "data": { "id": "1", "name": "John" }
439
+ }
440
+
441
+ // Success with list and pagination
442
+ {
443
+ "data": [{ "id": "1" }, { "id": "2" }],
444
+ "meta": {
445
+ "page": 1,
446
+ "limit": 20,
447
+ "total": 100,
448
+ "totalPages": 5
449
+ }
450
+ }
451
+
452
+ // Cursor pagination
453
+ {
454
+ "data": [...],
455
+ "meta": {
456
+ "nextCursor": "abc123",
457
+ "hasMore": true
458
+ }
459
+ }
460
+
461
+ // Error
462
+ {
463
+ "error": {
464
+ "code": "VALIDATION_ERROR",
465
+ "message": "Invalid input",
466
+ "details": [
467
+ { "field": "email", "message": "Invalid email format" }
468
+ ]
469
+ }
470
+ }
471
+ \`\`\`
472
+
473
+ ## ❌ DON'T
474
+ - Use verbs in URLs (/api/getUsers)
475
+ - Return 200 for errors
476
+ - Expose internal error details
477
+ - Skip input validation
478
+ - Ignore authentication/authorization
479
+ - Use inconsistent response formats
480
+
481
+ ## ✅ DO
482
+ - Use plural nouns for resources
483
+ - Return appropriate status codes
484
+ - Validate all inputs with schema
485
+ - Use consistent error format
486
+ - Implement pagination for lists
487
+ - Add rate limiting
488
+ - Include CORS headers
489
+ - Version your API (/api/v1/...)
490
+ - Document with OpenAPI/Swagger