Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 09:08:22 +08:00
commit a25d9dfcd0
28 changed files with 3680 additions and 0 deletions

389
commands/api/api-new.md Normal file
View File

@@ -0,0 +1,389 @@
# Create New API Endpoint (RepairCoin)
Create a new API endpoint for RepairCoin. This command supports both:
1. **Backend Express API** (Domain-Driven Design) - Primary use case
2. **Frontend Next.js API Routes** - For frontend-only features
---
## Part 1: Backend Express API (Primary)
Use this for main backend features requiring database access, blockchain interaction, or cross-domain events.
### Architecture
RepairCoin uses Domain-Driven Design with these domains:
- **admin** - Platform analytics, treasury, user management
- **customer** - Customer management, tiers, referrals, balances
- **shop** - Shop subscriptions, RCN purchasing, reward issuance
- **token** - RCN/RCG minting, redemption, cross-shop transfers
- **webhook** - FixFlow and Stripe webhook processing
### Directory Structure
```
backend/src/domains/{domain}/
├── {Domain}Domain.ts # Domain module
├── routes/
│ ├── index.ts # Main router
│ └── {feature}.ts # Feature routes
├── controllers/
│ └── {Feature}Controller.ts
└── services/
└── {Feature}Service.ts
```
### Step 1: Create Routes File
**Path**: `backend/src/domains/{domain}/routes/{feature}.ts`
```typescript
import { Router } from 'express';
import { requireRole, authMiddleware } from '../../../middleware/auth';
import {
validateRequired,
validateEthereumAddress,
validateEmail,
validateNumeric,
asyncHandler
} from '../../../middleware/errorHandler';
import { {Feature}Controller } from '../controllers/{Feature}Controller';
import { {Feature}Service } from '../services/{Feature}Service';
const router = Router();
// Initialize service and controller
const {feature}Service = new {Feature}Service();
const {feature}Controller = new {Feature}Controller({feature}Service);
/**
* @swagger
* /api/{domain}/{feature}:
* post:
* summary: {Description}
* tags: [{Domain}]
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - field1
* properties:
* field1:
* type: string
* responses:
* 200:
* description: Success
*/
router.post('/{feature}',
authMiddleware,
requireRole(['admin', 'shop']),
validateRequired(['field1']),
asyncHandler({feature}Controller.{method}.bind({feature}Controller))
);
export default router;
```
### Step 2: Create Controller
**Path**: `backend/src/domains/{domain}/controllers/{Feature}Controller.ts`
```typescript
import { Request, Response } from 'express';
import { {Feature}Service } from '../services/{Feature}Service';
import { ResponseHelper } from '../../../utils/responseHelper';
export class {Feature}Controller {
constructor(private {feature}Service: {Feature}Service) {}
async {method}(req: Request, res: Response) {
try {
const { field1, field2 } = req.body;
const { id } = req.params;
const result = await this.{feature}Service.{method}({
field1,
field2,
id,
userAddress: req.user?.address,
userRole: req.user?.role
});
ResponseHelper.success(res, result);
} catch (error: unknown) {
const err = error as Error;
if (err.message === 'Not found') {
ResponseHelper.notFound(res, err.message);
} else if (err.message === 'Unauthorized') {
ResponseHelper.forbidden(res, err.message);
} else if (err.message.includes('already exists')) {
ResponseHelper.conflict(res, err.message);
} else {
ResponseHelper.error(res, err.message, 500);
}
}
}
}
```
### Step 3: Create Service
**Path**: `backend/src/domains/{domain}/services/{Feature}Service.ts`
```typescript
import { logger } from '../../../utils/logger';
import { {Entity}Repository } from '../../../repositories/{Entity}Repository';
import { eventBus, createDomainEvent } from '../../../events/EventBus';
interface {Method}Input {
field1: string;
field2?: number;
userAddress?: string;
userRole?: string;
}
export class {Feature}Service {
private {entity}Repository: {Entity}Repository;
constructor() {
this.{entity}Repository = new {Entity}Repository();
}
async {method}(input: {Method}Input): Promise<unknown> {
logger.info('{Feature}Service.{method} called', { input });
try {
// Validation
if (!input.field1) {
throw new Error('field1 is required');
}
// Authorization
if (input.userRole !== 'admin') {
throw new Error('Unauthorized');
}
// Business logic
const result = await this.{entity}Repository.{operation}({
field1: input.field1
});
if (!result) {
throw new Error('Not found');
}
// Publish event
await eventBus.publish(createDomainEvent(
'{domain}.{event}',
result.id,
{ field1: input.field1 },
'{Feature}Service'
));
logger.info('{Feature}Service.{method} completed');
return {
success: true,
data: result
};
} catch (error: unknown) {
const err = error as Error;
logger.error('{Feature}Service.{method} error', {
error: err.message
});
throw error;
}
}
}
```
### Step 4: Register Routes
Update `backend/src/domains/{domain}/routes/index.ts`:
```typescript
import { Router } from 'express';
import {feature}Routes from './{feature}';
const router = Router();
router.use('/{feature}', {feature}Routes);
export default router;
```
### Middleware Options
```typescript
// Authentication
authMiddleware // JWT auth
// Authorization
requireRole(['admin']) // Admin only
requireRole(['admin', 'shop']) // Admin or Shop
requireRole(['customer']) // Customer only
// Validation
validateRequired(['field1', 'field2']) // Required fields
validateEthereumAddress('walletAddress') // Ethereum address
validateEmail('email') // Email format
validateNumeric('amount', 0.1, 1000) // Numeric range
```
### Response Helpers
```typescript
ResponseHelper.success(res, data, 'Message');
ResponseHelper.created(res, data, 'Created');
ResponseHelper.badRequest(res, 'Validation error');
ResponseHelper.unauthorized(res, 'Auth required');
ResponseHelper.forbidden(res, 'Insufficient permissions');
ResponseHelper.notFound(res, 'Not found');
ResponseHelper.conflict(res, 'Already exists');
ResponseHelper.error(res, 'Internal error', 500);
```
### Testing
**Path**: `backend/tests/{domain}/{feature}.test.ts`
```typescript
import request from 'supertest';
import { describe, it, expect, beforeAll } from '@jest/globals';
import RepairCoinApp from '../../src/app';
describe('{Feature} API', () => {
let app: unknown;
let token: string;
beforeAll(async () => {
process.env.NODE_ENV = 'test';
const repairCoinApp = new RepairCoinApp();
await repairCoinApp.initialize();
app = repairCoinApp.app;
const auth = await request(app as any)
.post('/api/auth/admin')
.send({ walletAddress: process.env.ADMIN_ADDRESSES?.split(',')[0] });
token = auth.body.token;
});
it('should create {feature}', async () => {
const response = await request(app as any)
.post('/api/{domain}/{feature}')
.set('Authorization', `Bearer ${token}`)
.send({ field1: 'value1' });
expect(response.status).toBe(200);
expect(response.body.success).toBe(true);
});
it('should reject unauthorized', async () => {
const response = await request(app as any)
.post('/api/{domain}/{feature}')
.send({ field1: 'value1' });
expect(response.status).toBe(401);
});
});
```
### Checklist
- [ ] Identified correct domain
- [ ] Created routes file with middleware
- [ ] Created controller with error handling
- [ ] Created service with business logic
- [ ] Registered routes in domain index
- [ ] Added Swagger documentation
- [ ] Added TypeScript types (no `any`)
- [ ] Implemented auth/validation
- [ ] Published domain events if needed
- [ ] Created integration tests
- [ ] Tested with auth token
---
## Part 2: Frontend Next.js API Route (Secondary)
Use this for frontend-only features (e.g., client-side data transformation, SSR helpers).
### Directory Structure
```
frontend/app/api/{route}/route.ts
```
### Implementation
```typescript
import { NextRequest, NextResponse } from 'next';
import { z } from 'zod';
// Validation schema
const RequestSchema = z.object({
field1: z.string().min(1),
field2: z.number().optional()
});
type RequestBody = z.infer<typeof RequestSchema>;
// Response helper
function success<T>(data: T) {
return NextResponse.json({ success: true, data });
}
function error(message: string, status: number = 500) {
return NextResponse.json(
{ success: false, error: message },
{ status }
);
}
export async function POST(req: NextRequest) {
try {
const body: unknown = await req.json();
// Validate
const validated = RequestSchema.parse(body) as RequestBody;
// Business logic
const result = {
id: '123',
...validated
};
return success(result);
} catch (err) {
if (err instanceof z.ZodError) {
return error(err.errors[0].message, 400);
}
return error('Internal error');
}
}
```
---
## Important Notes
1. **Never use `any` type** - Always use proper TypeScript types
2. **Always use asyncHandler** - For Express route error handling
3. **Use ResponseHelper** - Consistent API responses
4. **Bind controller methods** - `.bind(controller)` in routes
5. **Validate inputs** - Use validation middleware
6. **Check authorization** - In service layer
7. **Log operations** - Use logger for debugging
8. **Publish events** - For cross-domain communication
9. **Write tests** - Integration tests with auth
## Examples
- Customer API: `backend/src/domains/customer/`
- Shop API: `backend/src/domains/shop/routes/subscription.ts`
- Token API: `backend/src/domains/token/routes/redemptionSession.ts`

147
commands/api/api-protect.md Normal file
View File

@@ -0,0 +1,147 @@
---
description: Add authentication, authorization, and security to API endpoints
model: claude-sonnet-4-5
---
Add comprehensive security, authentication, and authorization to the specified API route.
## Target API Route
$ARGUMENTS
## Security Layers to Implement
###1. **Authentication** (Who are you?)
- Verify user identity
- Token validation (JWT, session, API keys)
- Handle expired/invalid tokens
### 2. **Authorization** (What can you do?)
- Role-based access control (RBAC)
- Resource-level permissions
- Check user ownership
### 3. **Input Validation**
- Sanitize all inputs
- SQL/NoSQL injection prevention
- XSS prevention
- Type validation with Zod
### 4. **Rate Limiting**
- Prevent abuse
- Per-user/IP limits
- Sliding window algorithm
### 5. **CORS** (if needed)
- Whitelist allowed origins
- Proper headers
- Credentials handling
## Implementation Approach
### For Supabase Projects:
```typescript
// Use Supabase Auth + RLS
- getUser() from server-side client
- RLS policies for data access
- Service role key for admin operations
```
### For NextAuth.js Projects:
```typescript
// Use NextAuth sessions
- getServerSession() in route handlers
- Protect with middleware
- Role checking logic
```
### For Custom Auth:
```typescript
// JWT validation
- Verify tokens
- Decode and validate claims
- Check expiration
```
## Security Checklist
**Authentication**
-  Verify authentication tokens
-  Handle missing/invalid tokens (401)
-  Check token expiration
-  Secure token storage recommendations
**Authorization**
-  Check user roles/permissions (403)
-  Verify resource ownership
-  Implement least privilege principle
-  Log authorization failures
**Input Validation**
-  Validate all inputs with Zod
-  Sanitize SQL/NoSQL inputs
-  Escape special characters
-  Limit payload sizes
**Rate Limiting**
-  Per-user limits
-  Per-IP limits
-  Clear error messages (429)
-  Retry-After headers
**CORS**
-  Whitelist specific origins
-  Handle preflight requests
-  Secure credentials
-  Appropriate headers
**Error Handling**
-  Don't expose stack traces
-  Generic error messages
-  Log detailed errors server-side
-  Consistent error format
**Logging & Monitoring**
-  Log authentication attempts
-  Log authorization failures
-  Track suspicious activity
-  Monitor rate limit hits
## What to Generate
1. **Protected Route Handler** - Secured version of the API route
2. **Middleware/Utilities** - Reusable auth helpers
3. **Type Definitions** - User, permissions, roles
4. **Error Responses** - Standardized auth errors
5. **Usage Examples** - Client-side integration
## Common Patterns for Solo Developers
**Pattern 1: Simple Token Auth**
```typescript
// For internal tools, admin panels
const token = request.headers.get('authorization')
if (token !== process.env.ADMIN_TOKEN) {
return new Response('Unauthorized', { status: 401 })
}
```
**Pattern 2: User-based Auth**
```typescript
// For user-facing apps
const user = await getCurrentUser(request)
if (!user) {
return new Response('Unauthorized', { status: 401 })
}
```
**Pattern 3: Role-based Auth**
```typescript
// For apps with different user types
const user = await getCurrentUser(request)
if (!user || !hasRole(user, 'admin')) {
return new Response('Forbidden', { status: 403 })
}
```
Generate production-ready, secure code that follows the principle of least privilege.

116
commands/api/api-test.md Normal file
View File

@@ -0,0 +1,116 @@
---
description: Test API endpoints with automated test generation
model: claude-sonnet-4-5
---
Generate comprehensive API tests for the specified endpoint.
## Target
$ARGUMENTS
## Test Strategy for Solo Developers
Create practical, maintainable tests using modern tools:
### 1. **Testing Approach**
- Unit tests for validation logic
- Integration tests for full API flow
- Edge case coverage
- Error scenario testing
### 2. **Tools** (choose based on project)
- **Vitest** - Fast, modern (recommended for new projects)
- **Jest** - Established, widely used
- **Supertest** - HTTP assertions
- **MSW** - API mocking
### 3. **Test Coverage**
**Happy Paths**
- Valid inputs return expected results
- Proper status codes
- Correct response structure
**Error Paths**
- Invalid input validation
- Authentication failures
- Rate limiting
- Server errors
- Missing required fields
**Edge Cases**
- Empty requests
- Malformed JSON
- Large payloads
- Special characters
- SQL injection attempts
- XSS attempts
### 4. **Test Structure**
```typescript
describe('API Endpoint', () => {
describe('Success Cases', () => {
it('should handle valid request', () => {})
it('should return correct status code', () => {})
})
describe('Validation', () => {
it('should reject invalid input', () => {})
it('should validate required fields', () => {})
})
describe('Error Handling', () => {
it('should handle server errors', () => {})
it('should return proper error format', () => {})
})
})
```
### 5. **What to Generate**
1. **Test File** - Complete test suite with all scenarios
2. **Mock Data** - Realistic test fixtures
3. **Helper Functions** - Reusable test utilities
4. **Setup/Teardown** - Database/state management
5. **Quick Test Script** - npm script to run tests
## Key Testing Principles
-  Test behavior, not implementation
-  Clear, descriptive test names
-  Arrange-Act-Assert pattern
-  Independent tests (no shared state)
-  Fast execution (<5s for unit tests)
-  Realistic mock data
-  Test error messages
- L Don't test framework internals
- L Don't mock what you don't own
- L Avoid brittle tests
## Additional Scenarios to Cover
1. **Authentication/Authorization**
- Valid tokens
- Expired tokens
- Missing tokens
- Invalid permissions
2. **Data Validation**
- Type mismatches
- Out of range values
- SQL/NoSQL injection
- XSS payloads
3. **Rate Limiting**
- Within limits
- Exceeding limits
- Reset behavior
4. **Performance**
- Response times
- Large dataset handling
- Concurrent requests
Generate production-ready tests I can run immediately with `npm test`.