Initial commit
This commit is contained in:
11
.claude-plugin/plugin.json
Normal file
11
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "development-skills",
|
||||
"description": "Reusable skills for code review, ADRs, API documentation, test generation, and performance profiling",
|
||||
"version": "1.0.0",
|
||||
"author": {
|
||||
"name": "Brock"
|
||||
},
|
||||
"skills": [
|
||||
"./skills"
|
||||
]
|
||||
}
|
||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# development-skills
|
||||
|
||||
Reusable skills for code review, ADRs, API documentation, test generation, and performance profiling
|
||||
61
plugin.lock.json
Normal file
61
plugin.lock.json
Normal file
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||
"pluginId": "gh:Dieshen/claude_marketplace:plugins/development-skills",
|
||||
"normalized": {
|
||||
"repo": null,
|
||||
"ref": "refs/tags/v20251128.0",
|
||||
"commit": "134df0ad0157ab8c4a7949e6ee174e8ab103b97a",
|
||||
"treeHash": "f471eb9d305e7b9478ef6c528be094dec1b9211706fa781a73bc977ed250ccb8",
|
||||
"generatedAt": "2025-11-28T10:10:25.019332Z",
|
||||
"toolVersion": "publish_plugins.py@0.2.0"
|
||||
},
|
||||
"origin": {
|
||||
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||
"branch": "master",
|
||||
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||
},
|
||||
"manifest": {
|
||||
"name": "development-skills",
|
||||
"description": "Reusable skills for code review, ADRs, API documentation, test generation, and performance profiling",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"content": {
|
||||
"files": [
|
||||
{
|
||||
"path": "README.md",
|
||||
"sha256": "b63b769ddbc49ca1e54f77089671ed4891448dff61554eeb8bc0d4b68603aa90"
|
||||
},
|
||||
{
|
||||
"path": ".claude-plugin/plugin.json",
|
||||
"sha256": "5cf7c8c173b9207f7eeb0663a4f803536d4f953a63b667413cdbe3f28a082e6a"
|
||||
},
|
||||
{
|
||||
"path": "skills/api-doc-generator.md",
|
||||
"sha256": "b87823388a1c9d28206d39ee8f433b0e324765dad04a58fb3709a971505d83dc"
|
||||
},
|
||||
{
|
||||
"path": "skills/test-case-generator.md",
|
||||
"sha256": "7ec6472e7008006d6a6c54612238d16ee6086d3b18a866509c04e993e9d1ec5b"
|
||||
},
|
||||
{
|
||||
"path": "skills/code-review.md",
|
||||
"sha256": "54e5bec5fe6679d1504377cdb918162552974a7ecfc18631677cc467e6c2e044"
|
||||
},
|
||||
{
|
||||
"path": "skills/performance-profiler.md",
|
||||
"sha256": "b9ff62ecbf7a04b234163edcf86d690444838ef93eb079f7053207cdc8a6e885"
|
||||
},
|
||||
{
|
||||
"path": "skills/adr-generator.md",
|
||||
"sha256": "7cecaee6863728bf78ce605bdd2c43b95a80188eebd8e11e383ef9728f6ea322"
|
||||
}
|
||||
],
|
||||
"dirSha256": "f471eb9d305e7b9478ef6c528be094dec1b9211706fa781a73bc977ed250ccb8"
|
||||
},
|
||||
"security": {
|
||||
"scannedAt": null,
|
||||
"scannerVersion": null,
|
||||
"flags": []
|
||||
}
|
||||
}
|
||||
325
skills/adr-generator.md
Normal file
325
skills/adr-generator.md
Normal file
@@ -0,0 +1,325 @@
|
||||
# Architecture Decision Record (ADR) Generator Skill
|
||||
|
||||
Generate Architecture Decision Records to document important architectural decisions.
|
||||
|
||||
## ADR Template
|
||||
|
||||
```markdown
|
||||
# ADR-{number}: {Title}
|
||||
|
||||
## Status
|
||||
{Proposed | Accepted | Deprecated | Superseded by ADR-XXX}
|
||||
|
||||
## Context
|
||||
What is the issue that we're seeing that is motivating this decision or change?
|
||||
|
||||
## Decision
|
||||
What is the change that we're proposing and/or doing?
|
||||
|
||||
## Consequences
|
||||
What becomes easier or more difficult to do because of this change?
|
||||
|
||||
### Positive
|
||||
- ...
|
||||
- ...
|
||||
|
||||
### Negative
|
||||
- ...
|
||||
- ...
|
||||
|
||||
### Neutral
|
||||
- ...
|
||||
|
||||
## Alternatives Considered
|
||||
What other options were evaluated?
|
||||
|
||||
### Alternative 1: {Name}
|
||||
**Description**: ...
|
||||
|
||||
**Pros**:
|
||||
- ...
|
||||
|
||||
**Cons**:
|
||||
- ...
|
||||
|
||||
**Why not chosen**: ...
|
||||
|
||||
### Alternative 2: {Name}
|
||||
**Description**: ...
|
||||
|
||||
**Pros**:
|
||||
- ...
|
||||
|
||||
**Cons**:
|
||||
- ...
|
||||
|
||||
**Why not chosen**: ...
|
||||
|
||||
## Implementation Notes
|
||||
Any specific implementation details or considerations.
|
||||
|
||||
## References
|
||||
- Link to relevant documentation
|
||||
- Link to related ADRs
|
||||
- Link to discussions
|
||||
```
|
||||
|
||||
## Common ADR Topics
|
||||
|
||||
### 1. Technology Selection
|
||||
- Programming languages
|
||||
- Frameworks and libraries
|
||||
- Databases
|
||||
- Cloud providers
|
||||
- Message queues
|
||||
- Caching solutions
|
||||
|
||||
### 2. Architecture Patterns
|
||||
- Microservices vs Monolith
|
||||
- Event-driven architecture
|
||||
- CQRS and Event Sourcing
|
||||
- API Gateway patterns
|
||||
- Service mesh adoption
|
||||
|
||||
### 3. Data Management
|
||||
- Database choice (SQL vs NoSQL)
|
||||
- Data modeling approach
|
||||
- Caching strategy
|
||||
- Data migration strategy
|
||||
- Backup and recovery
|
||||
|
||||
### 4. Security
|
||||
- Authentication mechanism
|
||||
- Authorization approach
|
||||
- Encryption standards
|
||||
- Secret management
|
||||
- API security
|
||||
|
||||
### 5. Development Practices
|
||||
- Branching strategy
|
||||
- Code review process
|
||||
- Testing strategy
|
||||
- CI/CD pipeline
|
||||
- Deployment strategy
|
||||
|
||||
### 6. Infrastructure
|
||||
- Hosting platform
|
||||
- Containerization strategy
|
||||
- Orchestration platform
|
||||
- Monitoring and logging
|
||||
- Disaster recovery
|
||||
|
||||
## Example ADR
|
||||
|
||||
```markdown
|
||||
# ADR-001: Use PostgreSQL for Primary Database
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
We need to select a database for our new e-commerce platform. The system needs to:
|
||||
- Handle complex relational data (users, orders, products, inventory)
|
||||
- Support ACID transactions for financial data
|
||||
- Scale to millions of records
|
||||
- Provide good query performance
|
||||
- Support full-text search
|
||||
- Be well-supported and documented
|
||||
|
||||
## Decision
|
||||
We will use PostgreSQL 16 as our primary database.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- **ACID compliance**: Ensures data consistency for financial transactions
|
||||
- **Rich data types**: JSON, arrays, and custom types provide flexibility
|
||||
- **Full-text search**: Built-in FTS capabilities reduce dependency on external search engines
|
||||
- **Mature ecosystem**: Excellent tooling, extensions, and community support
|
||||
- **Strong consistency**: Suitable for financial and inventory data
|
||||
- **Performance**: Query planner and indexing options provide good performance
|
||||
- **Cost-effective**: Open-source with no licensing fees
|
||||
- **Extensions**: PostGIS for location, pg_cron for scheduling, etc.
|
||||
|
||||
### Negative
|
||||
- **Vertical scaling**: Harder to scale horizontally compared to NoSQL
|
||||
- **Operational complexity**: Requires expertise for tuning and maintenance
|
||||
- **Read replicas**: Additional setup for read-heavy scaling
|
||||
- **Storage**: Can be more storage-intensive than some alternatives
|
||||
|
||||
### Neutral
|
||||
- **Learning curve**: Team has SQL experience, so moderate learning curve
|
||||
- **Hosting**: Available on all major cloud providers
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
### Alternative 1: MySQL
|
||||
**Description**: Popular open-source relational database
|
||||
|
||||
**Pros**:
|
||||
- Widely used and supported
|
||||
- Good performance for read-heavy workloads
|
||||
- Large ecosystem
|
||||
|
||||
**Cons**:
|
||||
- Less advanced features than PostgreSQL
|
||||
- JSON support not as robust
|
||||
- Less powerful full-text search
|
||||
- Some storage engines lack ACID compliance
|
||||
|
||||
**Why not chosen**: PostgreSQL offers more advanced features that align better with our requirements (JSON, full-text search, complex queries).
|
||||
|
||||
### Alternative 2: MongoDB
|
||||
**Description**: Document-oriented NoSQL database
|
||||
|
||||
**Pros**:
|
||||
- Flexible schema
|
||||
- Horizontal scaling
|
||||
- Fast writes
|
||||
- Good for rapidly changing data models
|
||||
|
||||
**Cons**:
|
||||
- Eventually consistent (can be configured for strong consistency with performance impact)
|
||||
- Less suitable for complex relational queries
|
||||
- Transactions across collections more complex
|
||||
- Not ideal for financial data
|
||||
|
||||
**Why not chosen**: Our data is highly relational and requires strong ACID guarantees for financial transactions.
|
||||
|
||||
### Alternative 3: Amazon DynamoDB
|
||||
**Description**: Fully managed NoSQL database service
|
||||
|
||||
**Pros**:
|
||||
- Fully managed, no ops overhead
|
||||
- Excellent scalability
|
||||
- Low latency
|
||||
- Pay per usage
|
||||
|
||||
**Cons**:
|
||||
- Vendor lock-in
|
||||
- Limited query capabilities
|
||||
- More expensive at scale
|
||||
- Requires different data modeling approach
|
||||
|
||||
**Why not chosen**: Relational model better fits our use case, and we want to avoid vendor lock-in.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
1. **Version**: Use PostgreSQL 16 for latest features
|
||||
2. **Hosting**: Deploy on AWS RDS for managed service benefits
|
||||
3. **Extensions**: Enable pg_trgm for fuzzy search, pg_stat_statements for monitoring
|
||||
4. **Connection Pooling**: Use PgBouncer for connection management
|
||||
5. **Backup**: Daily automated backups with point-in-time recovery
|
||||
6. **Monitoring**: CloudWatch metrics + custom dashboard
|
||||
7. **Read Replicas**: Configure 2 read replicas for read-heavy queries
|
||||
8. **Migration**: Use TypeORM migrations for schema changes
|
||||
|
||||
## References
|
||||
- [PostgreSQL Documentation](https://www.postgresql.org/docs/)
|
||||
- [AWS RDS PostgreSQL](https://aws.amazon.com/rds/postgresql/)
|
||||
- [Database Comparison Spike](https://company.com/docs/db-comparison)
|
||||
- [Team Discussion Thread](https://company.slack.com/archives/C123/p456)
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Number ADRs Sequentially
|
||||
Use ADR-001, ADR-002, etc. Never reuse numbers.
|
||||
|
||||
### 2. Keep ADRs Immutable
|
||||
Once accepted, don't modify. Create new ADR to supersede if needed.
|
||||
|
||||
### 3. Be Specific
|
||||
Include concrete technical details, not vague statements.
|
||||
|
||||
### 4. Document Trade-offs
|
||||
Every decision has pros and cons. Document both honestly.
|
||||
|
||||
### 5. Link Related ADRs
|
||||
Reference related decisions to show evolution.
|
||||
|
||||
### 6. Update Status
|
||||
Mark as Deprecated or Superseded when decision changes.
|
||||
|
||||
### 7. Include Team Input
|
||||
Document that stakeholders were consulted.
|
||||
|
||||
### 8. Write for Future Readers
|
||||
Someone reading 2 years later should understand why the decision was made.
|
||||
|
||||
### 9. Keep It Concise
|
||||
Aim for 1-2 pages. Link to detailed analysis separately.
|
||||
|
||||
### 10. Review Periodically
|
||||
Revisit ADRs annually to ensure they're still relevant.
|
||||
|
||||
## ADR Lifecycle
|
||||
|
||||
1. **Proposed**: Initial draft, under discussion
|
||||
2. **Accepted**: Team has agreed, implementation can proceed
|
||||
3. **Implemented**: Decision has been executed
|
||||
4. **Deprecated**: No longer recommended but not formally replaced
|
||||
5. **Superseded**: Replaced by a newer ADR
|
||||
|
||||
## Storage
|
||||
|
||||
Store ADRs in version control:
|
||||
```
|
||||
docs/
|
||||
architecture/
|
||||
decisions/
|
||||
001-use-postgresql.md
|
||||
002-adopt-microservices.md
|
||||
003-use-react-native.md
|
||||
README.md (index of all ADRs)
|
||||
```
|
||||
|
||||
## Index Template
|
||||
|
||||
```markdown
|
||||
# Architecture Decision Records
|
||||
|
||||
## Active
|
||||
- [ADR-001: Use PostgreSQL for Primary Database](001-use-postgresql.md)
|
||||
- [ADR-002: Adopt Microservices Architecture](002-adopt-microservices.md)
|
||||
|
||||
## Superseded
|
||||
- [ADR-003: Use Redux for State Management](003-use-redux.md) - Superseded by ADR-010
|
||||
|
||||
## Deprecated
|
||||
- None
|
||||
```
|
||||
|
||||
## Lightweight Alternative
|
||||
|
||||
For smaller decisions, use a simplified format:
|
||||
|
||||
```markdown
|
||||
# Decision: {Title}
|
||||
|
||||
## Context
|
||||
Brief context (2-3 sentences)
|
||||
|
||||
## Decision
|
||||
What we're doing (2-3 sentences)
|
||||
|
||||
## Trade-offs
|
||||
- **Pro**: ...
|
||||
- **Pro**: ...
|
||||
- **Con**: ...
|
||||
- **Con**: ...
|
||||
```
|
||||
|
||||
## Review Checklist
|
||||
|
||||
Before accepting an ADR:
|
||||
- [ ] Context clearly explains the problem
|
||||
- [ ] Decision is specific and actionable
|
||||
- [ ] Consequences (positive and negative) are documented
|
||||
- [ ] At least 2 alternatives were considered
|
||||
- [ ] Trade-offs are honestly assessed
|
||||
- [ ] Implementation notes provide enough detail
|
||||
- [ ] References are included
|
||||
- [ ] Stakeholders have reviewed
|
||||
- [ ] ADR number is assigned
|
||||
- [ ] Status is set correctly
|
||||
567
skills/api-doc-generator.md
Normal file
567
skills/api-doc-generator.md
Normal file
@@ -0,0 +1,567 @@
|
||||
# API Documentation Generator Skill
|
||||
|
||||
Automatically generate comprehensive API documentation from code.
|
||||
|
||||
## OpenAPI 3.0 Generation
|
||||
|
||||
### From Express.js/TypeScript
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* @openapi
|
||||
* /api/users:
|
||||
* get:
|
||||
* summary: List all users
|
||||
* tags: [Users]
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: page
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: Page number
|
||||
* - in: query
|
||||
* name: limit
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: Items per page
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* users:
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: '#/components/schemas/User'
|
||||
* pagination:
|
||||
* $ref: '#/components/schemas/Pagination'
|
||||
*/
|
||||
app.get('/api/users', async (req, res) => {
|
||||
// Implementation
|
||||
});
|
||||
```
|
||||
|
||||
### Complete OpenAPI Spec Template
|
||||
|
||||
```yaml
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
title: My API
|
||||
version: 1.0.0
|
||||
description: Comprehensive API for managing users and resources
|
||||
contact:
|
||||
name: API Support
|
||||
email: support@example.com
|
||||
license:
|
||||
name: MIT
|
||||
url: https://opensource.org/licenses/MIT
|
||||
|
||||
servers:
|
||||
- url: https://api.example.com/v1
|
||||
description: Production server
|
||||
- url: https://staging-api.example.com/v1
|
||||
description: Staging server
|
||||
- url: http://localhost:3000/v1
|
||||
description: Development server
|
||||
|
||||
tags:
|
||||
- name: Users
|
||||
description: User management endpoints
|
||||
- name: Authentication
|
||||
description: Authentication endpoints
|
||||
|
||||
paths:
|
||||
/auth/login:
|
||||
post:
|
||||
summary: User login
|
||||
tags: [Authentication]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required:
|
||||
- email
|
||||
- password
|
||||
properties:
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
example: user@example.com
|
||||
password:
|
||||
type: string
|
||||
format: password
|
||||
example: SecurePass123!
|
||||
responses:
|
||||
'200':
|
||||
description: Login successful
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
token:
|
||||
type: string
|
||||
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
user:
|
||||
$ref: '#/components/schemas/User'
|
||||
'401':
|
||||
description: Invalid credentials
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
|
||||
/users:
|
||||
get:
|
||||
summary: List users
|
||||
tags: [Users]
|
||||
security:
|
||||
- BearerAuth: []
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/PageParam'
|
||||
- $ref: '#/components/parameters/LimitParam'
|
||||
- in: query
|
||||
name: search
|
||||
schema:
|
||||
type: string
|
||||
description: Search term
|
||||
responses:
|
||||
'200':
|
||||
description: Success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/User'
|
||||
pagination:
|
||||
$ref: '#/components/schemas/Pagination'
|
||||
|
||||
post:
|
||||
summary: Create user
|
||||
tags: [Users]
|
||||
security:
|
||||
- BearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/CreateUserInput'
|
||||
responses:
|
||||
'201':
|
||||
description: User created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/User'
|
||||
'400':
|
||||
$ref: '#/components/responses/BadRequest'
|
||||
'401':
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
|
||||
/users/{id}:
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/UserIdParam'
|
||||
|
||||
get:
|
||||
summary: Get user by ID
|
||||
tags: [Users]
|
||||
security:
|
||||
- BearerAuth: []
|
||||
responses:
|
||||
'200':
|
||||
description: Success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/User'
|
||||
'404':
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
patch:
|
||||
summary: Update user
|
||||
tags: [Users]
|
||||
security:
|
||||
- BearerAuth: []
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UpdateUserInput'
|
||||
responses:
|
||||
'200':
|
||||
description: User updated
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/User'
|
||||
|
||||
delete:
|
||||
summary: Delete user
|
||||
tags: [Users]
|
||||
security:
|
||||
- BearerAuth: []
|
||||
responses:
|
||||
'204':
|
||||
description: User deleted
|
||||
'404':
|
||||
$ref: '#/components/responses/NotFound'
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
BearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
|
||||
parameters:
|
||||
UserIdParam:
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: User ID
|
||||
|
||||
PageParam:
|
||||
in: query
|
||||
name: page
|
||||
schema:
|
||||
type: integer
|
||||
minimum: 1
|
||||
default: 1
|
||||
description: Page number
|
||||
|
||||
LimitParam:
|
||||
in: query
|
||||
name: limit
|
||||
schema:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 100
|
||||
default: 20
|
||||
description: Items per page
|
||||
|
||||
schemas:
|
||||
User:
|
||||
type: object
|
||||
required:
|
||||
- id
|
||||
- email
|
||||
- name
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
example: usr_123abc
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
example: user@example.com
|
||||
name:
|
||||
type: string
|
||||
example: John Doe
|
||||
role:
|
||||
type: string
|
||||
enum: [user, admin]
|
||||
default: user
|
||||
createdAt:
|
||||
type: string
|
||||
format: date-time
|
||||
updatedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
CreateUserInput:
|
||||
type: object
|
||||
required:
|
||||
- email
|
||||
- name
|
||||
- password
|
||||
properties:
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
name:
|
||||
type: string
|
||||
minLength: 1
|
||||
maxLength: 100
|
||||
password:
|
||||
type: string
|
||||
format: password
|
||||
minLength: 8
|
||||
|
||||
UpdateUserInput:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
|
||||
Pagination:
|
||||
type: object
|
||||
properties:
|
||||
page:
|
||||
type: integer
|
||||
limit:
|
||||
type: integer
|
||||
totalPages:
|
||||
type: integer
|
||||
totalItems:
|
||||
type: integer
|
||||
hasNext:
|
||||
type: boolean
|
||||
hasPrevious:
|
||||
type: boolean
|
||||
|
||||
Error:
|
||||
type: object
|
||||
properties:
|
||||
code:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
details:
|
||||
type: object
|
||||
|
||||
responses:
|
||||
BadRequest:
|
||||
description: Bad request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
|
||||
Unauthorized:
|
||||
description: Unauthorized
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
|
||||
NotFound:
|
||||
description: Not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
```
|
||||
|
||||
## Generate from Code
|
||||
|
||||
### TypeScript/Express
|
||||
```typescript
|
||||
import swaggerJsdoc from 'swagger-jsdoc';
|
||||
import swaggerUi from 'swagger-ui-express';
|
||||
|
||||
const options = {
|
||||
definition: {
|
||||
openapi: '3.0.0',
|
||||
info: {
|
||||
title: 'My API',
|
||||
version: '1.0.0',
|
||||
},
|
||||
},
|
||||
apis: ['./src/routes/*.ts'],
|
||||
};
|
||||
|
||||
const specs = swaggerJsdoc(options);
|
||||
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs));
|
||||
```
|
||||
|
||||
### Python/FastAPI (Auto-generated)
|
||||
```python
|
||||
from fastapi import FastAPI, Query
|
||||
from pydantic import BaseModel
|
||||
|
||||
app = FastAPI(
|
||||
title="My API",
|
||||
description="API documentation",
|
||||
version="1.0.0"
|
||||
)
|
||||
|
||||
class User(BaseModel):
|
||||
id: str
|
||||
email: str
|
||||
name: str
|
||||
|
||||
@app.get("/users", response_model=list[User])
|
||||
async def list_users(
|
||||
page: int = Query(1, ge=1, description="Page number"),
|
||||
limit: int = Query(20, ge=1, le=100, description="Items per page")
|
||||
):
|
||||
"""
|
||||
List all users with pagination.
|
||||
|
||||
Returns a paginated list of users.
|
||||
"""
|
||||
pass
|
||||
# Docs auto-generated at /docs
|
||||
```
|
||||
|
||||
## README API Documentation
|
||||
|
||||
```markdown
|
||||
# API Documentation
|
||||
|
||||
## Base URL
|
||||
```
|
||||
https://api.example.com/v1
|
||||
```
|
||||
|
||||
## Authentication
|
||||
All endpoints require Bearer token authentication:
|
||||
```
|
||||
Authorization: Bearer YOUR_TOKEN_HERE
|
||||
```
|
||||
|
||||
## Endpoints
|
||||
|
||||
### List Users
|
||||
```http
|
||||
GET /users?page=1&limit=20
|
||||
```
|
||||
|
||||
**Query Parameters**:
|
||||
- `page` (integer, optional): Page number, default 1
|
||||
- `limit` (integer, optional): Items per page, default 20, max 100
|
||||
- `search` (string, optional): Search term
|
||||
|
||||
**Response 200**:
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": "usr_123",
|
||||
"email": "user@example.com",
|
||||
"name": "John Doe",
|
||||
"role": "user",
|
||||
"createdAt": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"page": 1,
|
||||
"totalPages": 5,
|
||||
"totalItems": 95
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Create User
|
||||
```http
|
||||
POST /users
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"email": "newuser@example.com",
|
||||
"name": "New User",
|
||||
"password": "SecurePass123!"
|
||||
}
|
||||
```
|
||||
|
||||
**Response 201**:
|
||||
```json
|
||||
{
|
||||
"id": "usr_456",
|
||||
"email": "newuser@example.com",
|
||||
"name": "New User",
|
||||
"role": "user",
|
||||
"createdAt": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## Error Responses
|
||||
|
||||
All errors follow this format:
|
||||
```json
|
||||
{
|
||||
"code": "ERROR_CODE",
|
||||
"message": "Human-readable message",
|
||||
"details": {}
|
||||
}
|
||||
```
|
||||
|
||||
### Status Codes
|
||||
- `200` - Success
|
||||
- `201` - Created
|
||||
- `204` - No Content
|
||||
- `400` - Bad Request
|
||||
- `401` - Unauthorized
|
||||
- `403` - Forbidden
|
||||
- `404` - Not Found
|
||||
- `422` - Validation Error
|
||||
- `429` - Rate Limit Exceeded
|
||||
- `500` - Internal Server Error
|
||||
|
||||
## Rate Limiting
|
||||
- 100 requests per minute per IP
|
||||
- 1000 requests per hour per user
|
||||
|
||||
## Code Examples
|
||||
|
||||
### JavaScript/Fetch
|
||||
```javascript
|
||||
const response = await fetch('https://api.example.com/v1/users', {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
const data = await response.json();
|
||||
```
|
||||
|
||||
### Python/Requests
|
||||
```python
|
||||
import requests
|
||||
|
||||
response = requests.get(
|
||||
'https://api.example.com/v1/users',
|
||||
headers={'Authorization': f'Bearer {token}'}
|
||||
)
|
||||
data = response.json()
|
||||
```
|
||||
|
||||
### cURL
|
||||
```bash
|
||||
curl -H "Authorization: Bearer YOUR_TOKEN" \
|
||||
https://api.example.com/v1/users
|
||||
```
|
||||
```
|
||||
|
||||
## Postman Collection
|
||||
|
||||
Generate Postman collection from OpenAPI:
|
||||
```bash
|
||||
openapi2postmanv2 -s openapi.yaml -o postman_collection.json
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Be Comprehensive**: Document all endpoints, parameters, and responses
|
||||
2. **Provide Examples**: Include real request/response examples
|
||||
3. **Document Errors**: Show all possible error responses
|
||||
4. **Code Samples**: Provide examples in multiple languages
|
||||
5. **Keep Updated**: Auto-generate from code when possible
|
||||
6. **Version APIs**: Include version in URL or headers
|
||||
7. **Security**: Document authentication clearly
|
||||
8. **Rate Limits**: Specify rate limiting rules
|
||||
9. **Changelog**: Maintain API changelog
|
||||
10. **Interactive Docs**: Use Swagger UI or similar
|
||||
|
||||
## Tools
|
||||
|
||||
- **Swagger UI**: Interactive API documentation
|
||||
- **Redoc**: Beautiful API documentation
|
||||
- **Postman**: API testing and documentation
|
||||
- **Insomnia**: API client and documentation
|
||||
- **Stoplight**: API design and documentation platform
|
||||
220
skills/code-review.md
Normal file
220
skills/code-review.md
Normal file
@@ -0,0 +1,220 @@
|
||||
# Code Review Skill
|
||||
|
||||
Perform comprehensive code reviews following industry best practices.
|
||||
|
||||
## Review Checklist
|
||||
|
||||
### 1. Code Quality
|
||||
- [ ] Follows coding standards and style guide
|
||||
- [ ] No code duplication (DRY principle)
|
||||
- [ ] Functions are small and focused (SRP)
|
||||
- [ ] Meaningful variable and function names
|
||||
- [ ] Appropriate use of comments (why, not what)
|
||||
- [ ] No magic numbers or strings
|
||||
- [ ] Proper error handling
|
||||
|
||||
### 2. Architecture & Design
|
||||
- [ ] SOLID principles applied
|
||||
- [ ] Appropriate design patterns used
|
||||
- [ ] Separation of concerns
|
||||
- [ ] Dependency injection where appropriate
|
||||
- [ ] No circular dependencies
|
||||
- [ ] Interfaces used for abstraction
|
||||
- [ ] Proper layering/modularity
|
||||
|
||||
### 3. Security
|
||||
- [ ] No hardcoded secrets or credentials
|
||||
- [ ] Input validation and sanitization
|
||||
- [ ] SQL injection prevention
|
||||
- [ ] XSS prevention
|
||||
- [ ] CSRF protection where needed
|
||||
- [ ] Proper authentication/authorization
|
||||
- [ ] Secure data transmission
|
||||
- [ ] No sensitive data in logs
|
||||
|
||||
### 4. Performance
|
||||
- [ ] Efficient algorithms and data structures
|
||||
- [ ] No N+1 queries
|
||||
- [ ] Proper indexing for database queries
|
||||
- [ ] Caching implemented where appropriate
|
||||
- [ ] No unnecessary computations
|
||||
- [ ] Lazy loading where appropriate
|
||||
- [ ] Resource cleanup (connections, files)
|
||||
|
||||
### 5. Testing
|
||||
- [ ] Unit tests present and passing
|
||||
- [ ] Integration tests where needed
|
||||
- [ ] Test coverage is adequate (>80% for critical paths)
|
||||
- [ ] Edge cases tested
|
||||
- [ ] Error conditions tested
|
||||
- [ ] Tests are maintainable
|
||||
- [ ] No flaky tests
|
||||
|
||||
### 6. Error Handling
|
||||
- [ ] All errors properly caught and handled
|
||||
- [ ] Meaningful error messages
|
||||
- [ ] Proper logging at appropriate levels
|
||||
- [ ] No swallowed exceptions
|
||||
- [ ] Graceful degradation
|
||||
- [ ] Retry logic where appropriate
|
||||
|
||||
### 7. Documentation
|
||||
- [ ] README updated if needed
|
||||
- [ ] API documentation present
|
||||
- [ ] Complex logic explained
|
||||
- [ ] Public APIs documented
|
||||
- [ ] Breaking changes noted
|
||||
- [ ] Migration guide if needed
|
||||
|
||||
### 8. Dependencies
|
||||
- [ ] No unnecessary dependencies
|
||||
- [ ] Dependencies are up to date
|
||||
- [ ] No known vulnerabilities
|
||||
- [ ] License compatibility checked
|
||||
- [ ] Bundle size impact considered
|
||||
|
||||
### 9. Database
|
||||
- [ ] Migrations are reversible
|
||||
- [ ] Indexes on foreign keys
|
||||
- [ ] No missing indexes for queries
|
||||
- [ ] Proper transaction handling
|
||||
- [ ] Connection pooling used
|
||||
- [ ] Data validation at DB level
|
||||
|
||||
### 10. API Design
|
||||
- [ ] RESTful principles followed
|
||||
- [ ] Consistent naming conventions
|
||||
- [ ] Proper HTTP methods and status codes
|
||||
- [ ] Versioning strategy in place
|
||||
- [ ] Rate limiting considered
|
||||
- [ ] Pagination for list endpoints
|
||||
|
||||
## Review Process
|
||||
|
||||
1. **Understand the Context**
|
||||
- Read the PR/commit description
|
||||
- Understand what problem is being solved
|
||||
- Review linked issues/tickets
|
||||
|
||||
2. **High-Level Review**
|
||||
- Check overall architecture
|
||||
- Verify design decisions
|
||||
- Look for major issues
|
||||
|
||||
3. **Detailed Review**
|
||||
- Go through code line by line
|
||||
- Check against checklist above
|
||||
- Note issues by severity
|
||||
|
||||
4. **Security Review**
|
||||
- Look for security vulnerabilities
|
||||
- Check authentication/authorization
|
||||
- Verify input validation
|
||||
|
||||
5. **Performance Review**
|
||||
- Look for performance issues
|
||||
- Check database queries
|
||||
- Review caching strategy
|
||||
|
||||
6. **Test Review**
|
||||
- Verify test coverage
|
||||
- Check test quality
|
||||
- Run tests locally
|
||||
|
||||
7. **Provide Feedback**
|
||||
- Categorize by severity: Critical, Major, Minor, Suggestion
|
||||
- Be specific and constructive
|
||||
- Provide examples or alternatives
|
||||
- Acknowledge good practices
|
||||
|
||||
## Severity Levels
|
||||
|
||||
**Critical**: Must be fixed before merge
|
||||
- Security vulnerabilities
|
||||
- Data loss scenarios
|
||||
- Breaking changes without migration
|
||||
- Production-breaking bugs
|
||||
|
||||
**Major**: Should be fixed before merge
|
||||
- Performance issues
|
||||
- Architectural violations
|
||||
- Missing error handling
|
||||
- Inadequate test coverage
|
||||
|
||||
**Minor**: Can be fixed later
|
||||
- Code style issues
|
||||
- Missing comments
|
||||
- Minor refactoring opportunities
|
||||
|
||||
**Suggestion**: Optional improvements
|
||||
- Alternative approaches
|
||||
- Future enhancements
|
||||
- Code organization ideas
|
||||
|
||||
## Example Review Comments
|
||||
|
||||
### Good Comments
|
||||
✅ "Consider using a Map instead of nested loops here for O(1) lookups. Current implementation is O(n²) which could be slow with large datasets."
|
||||
|
||||
✅ "This endpoint is missing authentication. Should we add the @RequireAuth decorator?"
|
||||
|
||||
✅ "Great use of the strategy pattern here! This makes adding new payment methods much easier."
|
||||
|
||||
### Bad Comments
|
||||
❌ "This is wrong."
|
||||
❌ "Why did you do it this way?"
|
||||
❌ "I would have done X instead."
|
||||
|
||||
## Automated Checks
|
||||
|
||||
Run these before manual review:
|
||||
```bash
|
||||
# Linting
|
||||
npm run lint
|
||||
|
||||
# Type checking
|
||||
npm run type-check
|
||||
|
||||
# Tests
|
||||
npm run test
|
||||
|
||||
# Security scan
|
||||
npm audit
|
||||
|
||||
# Code coverage
|
||||
npm run test:coverage
|
||||
```
|
||||
|
||||
## Focus Areas by Language
|
||||
|
||||
### JavaScript/TypeScript
|
||||
- Proper use of async/await
|
||||
- No console.log in production
|
||||
- TypeScript types used correctly
|
||||
- React hooks rules followed
|
||||
|
||||
### Python
|
||||
- PEP 8 compliance
|
||||
- Type hints used
|
||||
- Virtual environment used
|
||||
- Requirements.txt updated
|
||||
|
||||
### Go
|
||||
- Error handling (don't ignore errors)
|
||||
- Proper defer usage
|
||||
- Channel and goroutine safety
|
||||
- Context usage for cancellation
|
||||
|
||||
### Rust
|
||||
- Ownership rules followed
|
||||
- No unsafe blocks without justification
|
||||
- Error handling with Result/Option
|
||||
- Lifetime annotations correct
|
||||
|
||||
## Post-Review
|
||||
|
||||
After review is complete:
|
||||
- Mark as approved if all critical/major issues resolved
|
||||
- Request changes if issues remain
|
||||
- Follow up on suggested improvements
|
||||
- Document any technical debt created
|
||||
421
skills/performance-profiler.md
Normal file
421
skills/performance-profiler.md
Normal file
@@ -0,0 +1,421 @@
|
||||
# Performance Profiler Skill
|
||||
|
||||
Analyze code performance and provide optimization recommendations.
|
||||
|
||||
## Performance Analysis Checklist
|
||||
|
||||
### 1. Algorithm Complexity
|
||||
- [ ] Time complexity documented (O(n), O(n²), etc.)
|
||||
- [ ] Space complexity analyzed
|
||||
- [ ] No nested loops where not necessary
|
||||
- [ ] Efficient data structures chosen
|
||||
- [ ] Binary search used instead of linear where possible
|
||||
|
||||
### 2. Database Performance
|
||||
- [ ] Queries use appropriate indexes
|
||||
- [ ] No N+1 query problems
|
||||
- [ ] Connection pooling implemented
|
||||
- [ ] Batch operations used for bulk updates
|
||||
- [ ] Query execution plans analyzed
|
||||
|
||||
### 3. Caching
|
||||
- [ ] Expensive computations cached
|
||||
- [ ] API responses cached appropriately
|
||||
- [ ] Cache invalidation strategy in place
|
||||
- [ ] CDN used for static assets
|
||||
- [ ] Redis/Memcached for distributed caching
|
||||
|
||||
### 4. Network & I/O
|
||||
- [ ] API calls batched where possible
|
||||
- [ ] Compression enabled (gzip, brotli)
|
||||
- [ ] HTTP/2 or HTTP/3 used
|
||||
- [ ] Keep-alive connections
|
||||
- [ ] Parallel requests for independent data
|
||||
|
||||
### 5. Frontend Performance
|
||||
- [ ] Code splitting implemented
|
||||
- [ ] Lazy loading for routes/components
|
||||
- [ ] Images optimized and lazy loaded
|
||||
- [ ] Virtual scrolling for long lists
|
||||
- [ ] Debouncing/throttling on events
|
||||
- [ ] Memoization for expensive renders
|
||||
|
||||
### 6. Memory Management
|
||||
- [ ] No memory leaks
|
||||
- [ ] Event listeners cleaned up
|
||||
- [ ] Large objects garbage collected
|
||||
- [ ] Streams used for large files
|
||||
- [ ] WeakMap/WeakSet for cached objects
|
||||
|
||||
## Performance Profiling Tools
|
||||
|
||||
### Node.js
|
||||
```javascript
|
||||
// Built-in profiler
|
||||
node --prof app.js
|
||||
node --prof-process isolate-0xnnnnnnnnnnnn-v8.log > processed.txt
|
||||
|
||||
// Chrome DevTools
|
||||
node --inspect app.js
|
||||
// Then open chrome://inspect
|
||||
|
||||
// Clinic.js
|
||||
clinic doctor -- node app.js
|
||||
clinic flame -- node app.js
|
||||
clinic bubbleprof -- node app.js
|
||||
```
|
||||
|
||||
### Browser
|
||||
```javascript
|
||||
// Performance API
|
||||
performance.mark('start');
|
||||
// ... code to measure
|
||||
performance.mark('end');
|
||||
performance.measure('myOperation', 'start', 'end');
|
||||
const measures = performance.getEntriesByType('measure');
|
||||
console.log(measures[0].duration);
|
||||
|
||||
// Chrome DevTools Performance tab
|
||||
// Record → Run code → Stop → Analyze flame graph
|
||||
```
|
||||
|
||||
### Python
|
||||
```python
|
||||
import cProfile
|
||||
import pstats
|
||||
|
||||
# Profile function
|
||||
cProfile.run('my_function()', 'output.prof')
|
||||
|
||||
# Analyze results
|
||||
stats = pstats.Stats('output.prof')
|
||||
stats.sort_stats('cumulative')
|
||||
stats.print_stats(20) # Top 20 functions
|
||||
|
||||
# Line profiler
|
||||
from line_profiler import LineProfiler
|
||||
lp = LineProfiler()
|
||||
lp.add_function(my_function)
|
||||
lp.run('my_function()')
|
||||
lp.print_stats()
|
||||
```
|
||||
|
||||
## Common Performance Issues & Fixes
|
||||
|
||||
### Issue 1: N+1 Queries
|
||||
```typescript
|
||||
// ❌ Bad: N+1 queries
|
||||
const users = await User.findAll();
|
||||
for (const user of users) {
|
||||
user.posts = await Post.findAll({ where: { userId: user.id } });
|
||||
}
|
||||
|
||||
// ✅ Good: Single query with join
|
||||
const users = await User.findAll({
|
||||
include: [{ model: Post }]
|
||||
});
|
||||
|
||||
// ✅ Better: DataLoader for batching
|
||||
const postLoader = new DataLoader(async (userIds) => {
|
||||
const posts = await Post.findAll({
|
||||
where: { userId: { $in: userIds } }
|
||||
});
|
||||
return userIds.map(id => posts.filter(p => p.userId === id));
|
||||
});
|
||||
```
|
||||
|
||||
### Issue 2: Inefficient Loops
|
||||
```typescript
|
||||
// ❌ Bad: O(n²)
|
||||
function findDuplicates(arr: number[]): number[] {
|
||||
const duplicates = [];
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
for (let j = i + 1; j < arr.length; j++) {
|
||||
if (arr[i] === arr[j]) {
|
||||
duplicates.push(arr[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return duplicates;
|
||||
}
|
||||
|
||||
// ✅ Good: O(n)
|
||||
function findDuplicates(arr: number[]): number[] {
|
||||
const seen = new Set();
|
||||
const duplicates = new Set();
|
||||
for (const num of arr) {
|
||||
if (seen.has(num)) {
|
||||
duplicates.add(num);
|
||||
}
|
||||
seen.add(num);
|
||||
}
|
||||
return Array.from(duplicates);
|
||||
}
|
||||
```
|
||||
|
||||
### Issue 3: Large Lists Without Virtualization
|
||||
```typescript
|
||||
// ❌ Bad: Renders all 10,000 items
|
||||
{items.map(item => <ItemCard key={item.id} {...item} />)}
|
||||
|
||||
// ✅ Good: Virtual scrolling
|
||||
import { FixedSizeList } from 'react-window';
|
||||
|
||||
<FixedSizeList
|
||||
height={600}
|
||||
itemCount={items.length}
|
||||
itemSize={80}
|
||||
width="100%"
|
||||
>
|
||||
{({ index, style }) => (
|
||||
<div style={style}>
|
||||
<ItemCard {...items[index]} />
|
||||
</div>
|
||||
)}
|
||||
</FixedSizeList>
|
||||
```
|
||||
|
||||
### Issue 4: Unnecessary Re-renders
|
||||
```typescript
|
||||
// ❌ Bad: Re-renders on every parent render
|
||||
function ExpensiveComponent({ data }) {
|
||||
const processed = processData(data); // Runs every render
|
||||
return <div>{processed}</div>;
|
||||
}
|
||||
|
||||
// ✅ Good: Memoized
|
||||
const ExpensiveComponent = React.memo(({ data }) => {
|
||||
const processed = useMemo(() => processData(data), [data]);
|
||||
return <div>{processed}</div>;
|
||||
});
|
||||
```
|
||||
|
||||
### Issue 5: Blocking Operations
|
||||
```typescript
|
||||
// ❌ Bad: Blocks event loop
|
||||
function processLargeFile() {
|
||||
const data = fs.readFileSync('large-file.json'); // Blocks!
|
||||
return JSON.parse(data);
|
||||
}
|
||||
|
||||
// ✅ Good: Async
|
||||
async function processLargeFile() {
|
||||
const data = await fs.promises.readFile('large-file.json', 'utf8');
|
||||
return JSON.parse(data);
|
||||
}
|
||||
|
||||
// ✅ Better: Streaming
|
||||
function processLargeFileStream() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const stream = fs.createReadStream('large-file.json');
|
||||
let data = '';
|
||||
stream.on('data', chunk => data += chunk);
|
||||
stream.on('end', () => resolve(JSON.parse(data)));
|
||||
stream.on('error', reject);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Benchmarking
|
||||
|
||||
### JavaScript/TypeScript
|
||||
```typescript
|
||||
import Benchmark from 'benchmark';
|
||||
|
||||
const suite = new Benchmark.Suite();
|
||||
|
||||
suite
|
||||
.add('Array.forEach', () => {
|
||||
const arr = Array.from({ length: 1000 }, (_, i) => i);
|
||||
arr.forEach(x => x * 2);
|
||||
})
|
||||
.add('for loop', () => {
|
||||
const arr = Array.from({ length: 1000 }, (_, i) => i);
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
arr[i] * 2;
|
||||
}
|
||||
})
|
||||
.add('Array.map', () => {
|
||||
const arr = Array.from({ length: 1000 }, (_, i) => i);
|
||||
arr.map(x => x * 2);
|
||||
})
|
||||
.on('cycle', (event) => {
|
||||
console.log(String(event.target));
|
||||
})
|
||||
.on('complete', function() {
|
||||
console.log('Fastest is ' + this.filter('fastest').map('name'));
|
||||
})
|
||||
.run();
|
||||
```
|
||||
|
||||
### Python
|
||||
```python
|
||||
import timeit
|
||||
|
||||
def method1():
|
||||
return [x * 2 for x in range(1000)]
|
||||
|
||||
def method2():
|
||||
return list(map(lambda x: x * 2, range(1000)))
|
||||
|
||||
time1 = timeit.timeit(method1, number=10000)
|
||||
time2 = timeit.timeit(method2, number=10000)
|
||||
|
||||
print(f"Method 1: {time1:.4f}s")
|
||||
print(f"Method 2: {time2:.4f}s")
|
||||
```
|
||||
|
||||
## Database Query Optimization
|
||||
|
||||
### Analyze Slow Queries
|
||||
```sql
|
||||
-- PostgreSQL: Enable slow query logging
|
||||
ALTER SYSTEM SET log_min_duration_statement = 1000; -- Log queries > 1s
|
||||
SELECT pg_reload_conf();
|
||||
|
||||
-- View slow queries
|
||||
SELECT
|
||||
calls,
|
||||
total_exec_time,
|
||||
mean_exec_time,
|
||||
max_exec_time,
|
||||
query
|
||||
FROM pg_stat_statements
|
||||
ORDER BY mean_exec_time DESC
|
||||
LIMIT 20;
|
||||
|
||||
-- Explain query
|
||||
EXPLAIN ANALYZE
|
||||
SELECT u.*, COUNT(p.id) as post_count
|
||||
FROM users u
|
||||
LEFT JOIN posts p ON u.id = p.user_id
|
||||
GROUP BY u.id;
|
||||
```
|
||||
|
||||
### Add Indexes
|
||||
```sql
|
||||
-- Before: Sequential scan
|
||||
SELECT * FROM users WHERE email = 'user@example.com';
|
||||
-- Seq Scan on users (cost=0.00..180.00 rows=1)
|
||||
|
||||
-- Add index
|
||||
CREATE INDEX idx_users_email ON users(email);
|
||||
|
||||
-- After: Index scan
|
||||
-- Index Scan using idx_users_email on users (cost=0.42..8.44 rows=1)
|
||||
```
|
||||
|
||||
## Memory Leak Detection
|
||||
|
||||
### Node.js
|
||||
```javascript
|
||||
// Detect memory leaks
|
||||
const heapdump = require('heapdump');
|
||||
|
||||
// Take heap snapshot
|
||||
heapdump.writeSnapshot(`./heap-${Date.now()}.heapsnapshot`);
|
||||
|
||||
// Compare snapshots in Chrome DevTools
|
||||
// Memory → Load → Compare snapshots
|
||||
|
||||
// Monitor memory usage
|
||||
setInterval(() => {
|
||||
const used = process.memoryUsage();
|
||||
console.log({
|
||||
rss: `${Math.round(used.rss / 1024 / 1024)}MB`,
|
||||
heapTotal: `${Math.round(used.heapTotal / 1024 / 1024)}MB`,
|
||||
heapUsed: `${Math.round(used.heapUsed / 1024 / 1024)}MB`,
|
||||
external: `${Math.round(used.external / 1024 / 1024)}MB`,
|
||||
});
|
||||
}, 5000);
|
||||
```
|
||||
|
||||
## Performance Budget
|
||||
|
||||
Define acceptable performance metrics:
|
||||
|
||||
### Web Application
|
||||
- **First Contentful Paint (FCP)**: < 1.8s
|
||||
- **Largest Contentful Paint (LCP)**: < 2.5s
|
||||
- **Time to Interactive (TTI)**: < 3.8s
|
||||
- **Total Blocking Time (TBT)**: < 200ms
|
||||
- **Cumulative Layout Shift (CLS)**: < 0.1
|
||||
- **Bundle Size**: < 200KB (gzipped)
|
||||
|
||||
### API
|
||||
- **Response Time (p50)**: < 100ms
|
||||
- **Response Time (p95)**: < 500ms
|
||||
- **Response Time (p99)**: < 1000ms
|
||||
- **Throughput**: > 1000 req/s
|
||||
- **Error Rate**: < 0.1%
|
||||
|
||||
### Database
|
||||
- **Query Time (avg)**: < 50ms
|
||||
- **Connection Pool**: < 80% utilization
|
||||
- **Cache Hit Rate**: > 90%
|
||||
|
||||
## Optimization Priority
|
||||
|
||||
1. **Measure First**: Profile before optimizing
|
||||
2. **Focus on Bottlenecks**: 20% of code causes 80% of issues
|
||||
3. **User-Facing First**: Optimize what users experience
|
||||
4. **Low-Hanging Fruit**: Easy wins first
|
||||
5. **Monitor Continuously**: Set up alerts for regressions
|
||||
|
||||
## Performance Testing
|
||||
|
||||
```typescript
|
||||
// Load testing with autocannon
|
||||
import autocannon from 'autocannon';
|
||||
|
||||
autocannon({
|
||||
url: 'http://localhost:3000/api/users',
|
||||
connections: 100,
|
||||
duration: 30,
|
||||
headers: {
|
||||
'Authorization': 'Bearer token'
|
||||
}
|
||||
}, (err, result) => {
|
||||
console.log('Requests/sec:', result.requests.average);
|
||||
console.log('Latency p50:', result.latency.p50);
|
||||
console.log('Latency p99:', result.latency.p99);
|
||||
});
|
||||
```
|
||||
|
||||
## Report Template
|
||||
|
||||
```markdown
|
||||
# Performance Analysis Report
|
||||
|
||||
## Executive Summary
|
||||
- **Current Performance**: X req/s, Yms avg response
|
||||
- **Target Performance**: A req/s, Bms avg response
|
||||
- **Gap**: Need to improve by Z%
|
||||
|
||||
## Findings
|
||||
|
||||
### Critical Issues
|
||||
1. **N+1 Query in /api/users** (Impact: High)
|
||||
- Current: 500ms avg response time
|
||||
- Each user triggers 10 additional queries
|
||||
- **Recommendation**: Add eager loading with `include`
|
||||
- **Expected Impact**: Reduce to 50ms (10x improvement)
|
||||
|
||||
### Major Issues
|
||||
2. **Large Bundle Size** (Impact: Medium)
|
||||
- Current: 800KB (gzipped)
|
||||
- **Recommendation**: Code splitting, lazy loading
|
||||
- **Expected Impact**: Reduce to 200KB
|
||||
|
||||
## Optimization Roadmap
|
||||
|
||||
1. **Week 1**: Fix N+1 queries (High impact, Low effort)
|
||||
2. **Week 2**: Implement caching (High impact, Medium effort)
|
||||
3. **Week 3**: Code splitting (Medium impact, Medium effort)
|
||||
4. **Week 4**: Database indexing (Medium impact, Low effort)
|
||||
|
||||
## Success Metrics
|
||||
- Response time reduced by 60%
|
||||
- Throughput increased by 3x
|
||||
- Error rate reduced to < 0.1%
|
||||
```
|
||||
346
skills/test-case-generator.md
Normal file
346
skills/test-case-generator.md
Normal file
@@ -0,0 +1,346 @@
|
||||
# Test Case Generator Skill
|
||||
|
||||
Generate comprehensive test cases from requirements and code.
|
||||
|
||||
## Test Case Template
|
||||
|
||||
```markdown
|
||||
## Test Case: {ID} - {Title}
|
||||
|
||||
**Priority**: Critical | High | Medium | Low
|
||||
**Type**: Unit | Integration | E2E | Performance | Security
|
||||
**Status**: Pending | Pass | Fail | Blocked
|
||||
|
||||
### Preconditions
|
||||
- System is running
|
||||
- User is authenticated
|
||||
- Database contains test data
|
||||
|
||||
### Test Steps
|
||||
1. Navigate to login page
|
||||
2. Enter valid credentials
|
||||
3. Click "Login" button
|
||||
4. Verify redirect to dashboard
|
||||
|
||||
### Expected Results
|
||||
- User is logged in
|
||||
- Dashboard displays user's name
|
||||
- Session token is stored
|
||||
- Analytics event is fired
|
||||
|
||||
### Actual Results
|
||||
{To be filled during test execution}
|
||||
|
||||
### Test Data
|
||||
```json
|
||||
{
|
||||
"email": "test@example.com",
|
||||
"password": "Test123!"
|
||||
}
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
- Database seeded with test user
|
||||
- Email service mocked
|
||||
|
||||
### Notes
|
||||
- Tests authentication flow
|
||||
- Covers happy path
|
||||
```
|
||||
|
||||
## Generate Unit Tests
|
||||
|
||||
### From Function Specification
|
||||
|
||||
**Function**: `calculateDiscount(price: number, couponCode: string): number`
|
||||
|
||||
**Requirements**:
|
||||
- Apply 10% discount for "SAVE10"
|
||||
- Apply 20% discount for "SAVE20"
|
||||
- Return original price for invalid codes
|
||||
- Throw error for negative prices
|
||||
|
||||
**Generated Tests**:
|
||||
```typescript
|
||||
describe('calculateDiscount', () => {
|
||||
it('should apply 10% discount with SAVE10 code', () => {
|
||||
expect(calculateDiscount(100, 'SAVE10')).toBe(90);
|
||||
});
|
||||
|
||||
it('should apply 20% discount with SAVE20 code', () => {
|
||||
expect(calculateDiscount(100, 'SAVE20')).toBe(80);
|
||||
});
|
||||
|
||||
it('should return original price for invalid code', () => {
|
||||
expect(calculateDiscount(100, 'INVALID')).toBe(100);
|
||||
});
|
||||
|
||||
it('should return original price for empty code', () => {
|
||||
expect(calculateDiscount(100, '')).toBe(100);
|
||||
});
|
||||
|
||||
it('should throw error for negative price', () => {
|
||||
expect(() => calculateDiscount(-10, 'SAVE10')).toThrow('Price must be positive');
|
||||
});
|
||||
|
||||
it('should handle zero price', () => {
|
||||
expect(calculateDiscount(0, 'SAVE10')).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle decimal prices', () => {
|
||||
expect(calculateDiscount(99.99, 'SAVE10')).toBeCloseTo(89.99, 2);
|
||||
});
|
||||
|
||||
it('should be case insensitive for coupon codes', () => {
|
||||
expect(calculateDiscount(100, 'save10')).toBe(90);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Test Matrix Generation
|
||||
|
||||
### Feature: User Registration
|
||||
|
||||
| Test Case | Email | Password | Name | Expected Result |
|
||||
|-----------|-------|----------|------|-----------------|
|
||||
| TC-001 | valid@email.com | Password123! | John Doe | Success |
|
||||
| TC-002 | invalid-email | Password123! | John Doe | Validation Error |
|
||||
| TC-003 | valid@email.com | short | John Doe | Password too short |
|
||||
| TC-004 | valid@email.com | nouppercasenumber! | John Doe | Password requirements not met |
|
||||
| TC-005 | valid@email.com | Password123! | "" | Name required error |
|
||||
| TC-006 | duplicate@email.com | Password123! | Jane Doe | Email already exists |
|
||||
| TC-007 | valid@email.com | Password123! | A | Success (minimum length) |
|
||||
| TC-008 | valid@email.com | Password123! | {101 chars} | Name too long error |
|
||||
|
||||
## Edge Cases Identification
|
||||
|
||||
For any feature, generate tests for:
|
||||
|
||||
### Input Validation
|
||||
- Minimum boundary (0, 1, "")
|
||||
- Maximum boundary (MAX_INT, max length)
|
||||
- Just below minimum (-1, empty string)
|
||||
- Just above maximum (MAX_INT + 1, max length + 1)
|
||||
- Invalid types (null, undefined, NaN)
|
||||
- Special characters (', ", <, >, &, SQL injection)
|
||||
- Unicode characters (emoji, RTL text)
|
||||
|
||||
### State Transitions
|
||||
- Initial state → Valid transition → Expected state
|
||||
- Invalid state transitions
|
||||
- Concurrent state changes
|
||||
- Idempotency (multiple identical requests)
|
||||
|
||||
### Error Conditions
|
||||
- Network failures
|
||||
- Timeout scenarios
|
||||
- Partial data
|
||||
- Corrupted data
|
||||
- Permission denied
|
||||
- Resource exhaustion
|
||||
|
||||
### Performance
|
||||
- Single item
|
||||
- Empty list
|
||||
- Large dataset (10K+ items)
|
||||
- Concurrent requests
|
||||
- Memory leaks
|
||||
- Long-running operations
|
||||
|
||||
## Integration Test Generation
|
||||
|
||||
### API Endpoint Testing
|
||||
|
||||
```typescript
|
||||
describe('POST /api/users', () => {
|
||||
beforeEach(async () => {
|
||||
await db.reset();
|
||||
});
|
||||
|
||||
it('should create user with valid data', async () => {
|
||||
const response = await request(app)
|
||||
.post('/api/users')
|
||||
.send({
|
||||
email: 'test@example.com',
|
||||
name: 'Test User',
|
||||
password: 'Test123!'
|
||||
});
|
||||
|
||||
expect(response.status).toBe(201);
|
||||
expect(response.body).toHaveProperty('id');
|
||||
expect(response.body.email).toBe('test@example.com');
|
||||
|
||||
// Verify in database
|
||||
const user = await db.users.findByEmail('test@example.com');
|
||||
expect(user).toBeDefined();
|
||||
});
|
||||
|
||||
it('should reject duplicate email', async () => {
|
||||
await db.users.create({ email: 'existing@example.com' });
|
||||
|
||||
const response = await request(app)
|
||||
.post('/api/users')
|
||||
.send({ email: 'existing@example.com', name: 'Test', password: 'Test123!' });
|
||||
|
||||
expect(response.status).toBe(409);
|
||||
expect(response.body.code).toBe('EMAIL_EXISTS');
|
||||
});
|
||||
|
||||
it('should hash password before storing', async () => {
|
||||
const password = 'PlainTextPassword';
|
||||
|
||||
await request(app)
|
||||
.post('/api/users')
|
||||
.send({ email: 'test@example.com', name: 'Test', password });
|
||||
|
||||
const user = await db.users.findByEmail('test@example.com');
|
||||
expect(user.password).not.toBe(password);
|
||||
expect(user.password).toMatch(/^\$2[aby]\$.{56}$/); // bcrypt format
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## E2E Test Scenarios
|
||||
|
||||
### User Journey: Complete Purchase
|
||||
|
||||
```typescript
|
||||
test('user can complete purchase from product page to confirmation', async ({ page }) => {
|
||||
// 1. Login
|
||||
await page.goto('/login');
|
||||
await page.fill('[name="email"]', 'buyer@example.com');
|
||||
await page.fill('[name="password"]', 'Test123!');
|
||||
await page.click('button[type="submit"]');
|
||||
await expect(page).toHaveURL('/dashboard');
|
||||
|
||||
// 2. Browse and add to cart
|
||||
await page.goto('/products/laptop-pro');
|
||||
await page.click('[data-testid="add-to-cart"]');
|
||||
await expect(page.locator('[data-testid="cart-count"]')).toHaveText('1');
|
||||
|
||||
// 3. Go to cart
|
||||
await page.click('[data-testid="cart-icon"]');
|
||||
await expect(page).toHaveURL('/cart');
|
||||
await expect(page.locator('[data-testid="cart-item"]')).toHaveCount(1);
|
||||
|
||||
// 4. Proceed to checkout
|
||||
await page.click('[data-testid="checkout-button"]');
|
||||
await expect(page).toHaveURL('/checkout');
|
||||
|
||||
// 5. Fill shipping info
|
||||
await page.fill('[name="address"]', '123 Main St');
|
||||
await page.fill('[name="city"]', 'New York');
|
||||
await page.fill('[name="zip"]', '10001');
|
||||
await page.click('[data-testid="continue-payment"]');
|
||||
|
||||
// 6. Fill payment info (test card)
|
||||
await page.fill('[name="cardNumber"]', '4242424242424242');
|
||||
await page.fill('[name="expiry"]', '12/25');
|
||||
await page.fill('[name="cvc"]', '123');
|
||||
|
||||
// 7. Place order
|
||||
await page.click('[data-testid="place-order"]');
|
||||
|
||||
// 8. Verify confirmation
|
||||
await expect(page).toHaveURL(/\/orders\/[a-zA-Z0-9]+/);
|
||||
await expect(page.locator('text=Order Confirmed')).toBeVisible();
|
||||
|
||||
// 9. Verify email sent (mock)
|
||||
expect(emailService.send).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
to: 'buyer@example.com',
|
||||
subject: expect.stringContaining('Order Confirmation')
|
||||
})
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
## Test Data Generation
|
||||
|
||||
### Factory Pattern
|
||||
|
||||
```typescript
|
||||
class UserFactory {
|
||||
static create(overrides?: Partial<User>): User {
|
||||
return {
|
||||
id: faker.datatype.uuid(),
|
||||
email: faker.internet.email(),
|
||||
name: faker.name.fullName(),
|
||||
role: 'user',
|
||||
createdAt: new Date(),
|
||||
...overrides
|
||||
};
|
||||
}
|
||||
|
||||
static createAdmin(overrides?: Partial<User>): User {
|
||||
return this.create({ role: 'admin', ...overrides });
|
||||
}
|
||||
|
||||
static createMany(count: number): User[] {
|
||||
return Array.from({ length: count }, () => this.create());
|
||||
}
|
||||
}
|
||||
|
||||
// Usage
|
||||
const user = UserFactory.create({ email: 'specific@example.com' });
|
||||
const admin = UserFactory.createAdmin();
|
||||
const users = UserFactory.createMany(100);
|
||||
```
|
||||
|
||||
## Checklist for Complete Test Coverage
|
||||
|
||||
### Functionality
|
||||
- [ ] Happy path (expected usage)
|
||||
- [ ] Alternative paths
|
||||
- [ ] Error conditions
|
||||
- [ ] Edge cases
|
||||
- [ ] Boundary conditions
|
||||
|
||||
### Data
|
||||
- [ ] Valid data
|
||||
- [ ] Invalid data
|
||||
- [ ] Missing data (null, undefined)
|
||||
- [ ] Empty data
|
||||
- [ ] Extreme values
|
||||
|
||||
### State
|
||||
- [ ] Initial state
|
||||
- [ ] Valid state transitions
|
||||
- [ ] Invalid state transitions
|
||||
- [ ] Final/terminal states
|
||||
|
||||
### Integration
|
||||
- [ ] Database operations
|
||||
- [ ] External API calls
|
||||
- [ ] File system operations
|
||||
- [ ] Third-party services
|
||||
|
||||
### Security
|
||||
- [ ] Authentication required
|
||||
- [ ] Authorization enforced
|
||||
- [ ] Input sanitization
|
||||
- [ ] SQL injection prevention
|
||||
- [ ] XSS prevention
|
||||
|
||||
### Performance
|
||||
- [ ] Response time acceptable
|
||||
- [ ] Handles high load
|
||||
- [ ] No memory leaks
|
||||
- [ ] Efficient queries
|
||||
|
||||
### Usability
|
||||
- [ ] Error messages clear
|
||||
- [ ] Loading states shown
|
||||
- [ ] Success feedback provided
|
||||
- [ ] Accessibility requirements met
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Test Behavior, Not Implementation**: Focus on what the code does, not how
|
||||
2. **One Assert Per Test**: Makes failures easier to diagnose
|
||||
3. **Descriptive Names**: Test name should describe what and why
|
||||
4. **Arrange-Act-Assert**: Clear test structure
|
||||
5. **Independent Tests**: No dependencies between tests
|
||||
6. **Fast Tests**: Unit tests should run in milliseconds
|
||||
7. **Deterministic**: Same input always produces same output
|
||||
8. **Readable**: Tests serve as documentation
|
||||
Reference in New Issue
Block a user