metacoding 1.5.0 → 2.0.1
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.
- package/CHANGELOG.md +59 -0
- package/README.md +108 -514
- package/lib/cli.d.ts.map +1 -1
- package/lib/cli.js +18 -19
- package/lib/cli.js.map +1 -1
- package/lib/commands/init.d.ts +8 -14
- package/lib/commands/init.d.ts.map +1 -1
- package/lib/commands/init.js +105 -387
- package/lib/commands/init.js.map +1 -1
- package/lib/commands/update.d.ts +9 -9
- package/lib/commands/update.d.ts.map +1 -1
- package/lib/commands/update.js +141 -320
- package/lib/commands/update.js.map +1 -1
- package/lib/services/backup.d.ts +1 -1
- package/lib/services/backup.d.ts.map +1 -1
- package/lib/services/backup.js +10 -6
- package/lib/services/backup.js.map +1 -1
- package/lib/services/filesystem.d.ts.map +1 -1
- package/lib/services/filesystem.js +11 -5
- package/lib/services/filesystem.js.map +1 -1
- package/lib/services/gitignore-manager.js +5 -5
- package/lib/services/gitignore-manager.js.map +1 -1
- package/lib/services/project-detector.d.ts +9 -8
- package/lib/services/project-detector.d.ts.map +1 -1
- package/lib/services/project-detector.js +79 -197
- package/lib/services/project-detector.js.map +1 -1
- package/lib/services/skill-manager.d.ts +23 -0
- package/lib/services/skill-manager.d.ts.map +1 -0
- package/lib/services/skill-manager.js +212 -0
- package/lib/services/skill-manager.js.map +1 -0
- package/lib/types/index.d.ts +5 -15
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +9 -17
- package/skills/metacoding-workflow/SKILL.md +52 -0
- package/skills/metacoding-workflow/agents/openai.yaml +4 -0
- package/skills/metacoding-workflow/assets/templates/changelog-entry.md +6 -0
- package/skills/metacoding-workflow/assets/templates/project-context.md +18 -0
- package/skills/metacoding-workflow/assets/templates/repeated-task-checklist.md +8 -0
- package/skills/metacoding-workflow/assets/templates/task-entry.md +9 -0
- package/skills/metacoding-workflow/assets/templates/test-plan.md +8 -0
- package/skills/metacoding-workflow/references/javascript.md +7 -0
- package/skills/metacoding-workflow/references/node.md +7 -0
- package/skills/metacoding-workflow/references/platform-adaptation.md +37 -0
- package/skills/metacoding-workflow/references/python.md +7 -0
- package/skills/metacoding-workflow/references/react.md +7 -0
- package/skills/metacoding-workflow/references/repository-organization.md +84 -0
- package/skills/metacoding-workflow/references/typescript.md +7 -0
- package/skills/metacoding-workflow/references/workflow-rules.md +54 -0
- package/skills/vendor-templates/claude-agent.md.template +41 -0
- package/lib/services/assistant-adapter.d.ts +0 -18
- package/lib/services/assistant-adapter.d.ts.map +0 -1
- package/lib/services/assistant-adapter.js +0 -246
- package/lib/services/assistant-adapter.js.map +0 -1
- package/lib/services/cursor.d.ts +0 -47
- package/lib/services/cursor.d.ts.map +0 -1
- package/lib/services/cursor.js +0 -314
- package/lib/services/cursor.js.map +0 -1
- package/lib/services/template-manager.d.ts +0 -23
- package/lib/services/template-manager.d.ts.map +0 -1
- package/lib/services/template-manager.js +0 -374
- package/lib/services/template-manager.js.map +0 -1
- package/lib/services/vscode.d.ts +0 -10
- package/lib/services/vscode.d.ts.map +0 -1
- package/lib/services/vscode.js +0 -108
- package/lib/services/vscode.js.map +0 -1
- package/templates/assistants/AGENTS.md +0 -203
- package/templates/assistants/CLAUDE.md +0 -156
- package/templates/assistants/GEMINI.md +0 -193
- package/templates/general/code-review.instructions.md +0 -265
- package/templates/general/copilot-instructions.md +0 -427
- package/templates/general/docs-update.instructions.md +0 -275
- package/templates/general/release.instructions.md +0 -242
- package/templates/general/template.json +0 -9
- package/templates/general/test-runner.instructions.md +0 -188
- package/templates/javascript/javascript.coding.instructions.md +0 -500
- package/templates/javascript/javascript.docs.instructions.md +0 -563
- package/templates/javascript/javascript.testing.instructions.md +0 -686
- package/templates/javascript/template.json +0 -36
- package/templates/node/nodejs.coding.instructions.md +0 -249
- package/templates/node/nodejs.docs.instructions.md +0 -261
- package/templates/node/nodejs.testing.instructions.md +0 -373
- package/templates/node/template.json +0 -23
- package/templates/python/python.coding.instructions.md +0 -338
- package/templates/python/python.docs.instructions.md +0 -1178
- package/templates/python/python.testing.instructions.md +0 -1073
- package/templates/python/template.json +0 -75
- package/templates/react/react.coding.instructions.md +0 -694
- package/templates/react/react.docs.instructions.md +0 -451
- package/templates/react/react.testing.instructions.md +0 -192
- package/templates/react/template.json +0 -14
- package/templates/react/test-runner.instructions.md +0 -135
- package/templates/typescript/template.json +0 -16
- package/templates/typescript/typescript.coding.instructions.md +0 -368
- package/templates/typescript/typescript.docs.instructions.md +0 -760
- package/templates/typescript/typescript.testing.instructions.md +0 -739
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: 'React/Frontend testing guidelines and workflow'
|
|
3
|
-
applyTo: 'test/**/*'
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# React/Frontend Test Execution Guidelines
|
|
7
|
-
|
|
8
|
-
## Pre-Commit Testing Workflow
|
|
9
|
-
|
|
10
|
-
- **Run all tests before committing changes:** Use `npm test` or `yarn test`
|
|
11
|
-
- **Ensure tests pass in both development and CI environments**
|
|
12
|
-
- **Fix failing tests before proceeding with commits**
|
|
13
|
-
- **Run specific test suites for targeted changes when appropriate**
|
|
14
|
-
- **Verify test coverage meets project standards**
|
|
15
|
-
|
|
16
|
-
## Test Development Standards
|
|
17
|
-
|
|
18
|
-
- **New Features:** Ensure all new React components have corresponding unit tests
|
|
19
|
-
- **Test Coverage:** Aim for high coverage of critical functionality paths
|
|
20
|
-
- **Test Documentation:** Follow standardized table format in `test/test-documentation.md` for all test cases
|
|
21
|
-
- **Test Organization:** Group related tests with clear hierarchy and descriptive names
|
|
22
|
-
- **React-Specific Patterns:** Follow React Testing Library patterns and best practices
|
|
23
|
-
|
|
24
|
-
## React/Frontend Testing Guidelines
|
|
25
|
-
|
|
26
|
-
For detailed React testing frameworks and patterns, refer to:
|
|
27
|
-
|
|
28
|
-
- **React Testing Library:** Component testing with user-centric approach
|
|
29
|
-
- **Jest:** Unit testing framework with snapshot testing
|
|
30
|
-
- **Cypress/Playwright:** End-to-end testing for user workflows
|
|
31
|
-
- **Storybook:** Component documentation and visual testing
|
|
32
|
-
|
|
33
|
-
## Test Case Documentation Format
|
|
34
|
-
|
|
35
|
-
All test cases must be documented using the standardized table format:
|
|
36
|
-
|
|
37
|
-
```markdown
|
|
38
|
-
| Test Case ID | Description | Type | Status |
|
|
39
|
-
| :------------ | :------------------------------------------ | :--- | :-------- |
|
|
40
|
-
| AREA-TYPE-001 | Brief but descriptive test case description | Unit | Completed |
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## React/Frontend Test Case Naming Conventions
|
|
44
|
-
|
|
45
|
-
### Test Case ID Format: `[AREA]-[TYPE]-[NUMBER]`
|
|
46
|
-
|
|
47
|
-
**React/Frontend Area Prefixes:**
|
|
48
|
-
|
|
49
|
-
- `COMP` - React component tests
|
|
50
|
-
- `HOOK` - Custom hooks tests
|
|
51
|
-
- `PAGE` - Page/Route component tests
|
|
52
|
-
- `UTIL` - Frontend utility function tests
|
|
53
|
-
- `STORE` - State management tests (Redux/Zustand/Context)
|
|
54
|
-
- `API` - Frontend API client tests
|
|
55
|
-
- `FORM` - Form validation and submission tests
|
|
56
|
-
- `UI` - UI interaction and behavior tests
|
|
57
|
-
- `A11Y` - Accessibility compliance tests
|
|
58
|
-
- `PERF` - Performance and optimization tests
|
|
59
|
-
|
|
60
|
-
**Type Suffixes:**
|
|
61
|
-
|
|
62
|
-
- `UNIT` - Unit tests (isolated component testing)
|
|
63
|
-
- `INT` - Integration tests (component interaction testing)
|
|
64
|
-
- `E2E` - End-to-end tests (full user workflow testing)
|
|
65
|
-
|
|
66
|
-
**Examples:**
|
|
67
|
-
|
|
68
|
-
- `COMP-UNIT-001` - First unit test for React Component
|
|
69
|
-
- `HOOK-UNIT-001` - First unit test for Custom Hook
|
|
70
|
-
- `PAGE-E2E-001` - First end-to-end test for Page Component
|
|
71
|
-
- `FORM-INT-001` - First integration test for Form Component
|
|
72
|
-
|
|
73
|
-
### Test Method Naming
|
|
74
|
-
|
|
75
|
-
Use React-specific naming conventions:
|
|
76
|
-
|
|
77
|
-
- **Component Tests:** `ComponentName_scenario_expectedOutcome`
|
|
78
|
-
- **Hook Tests:** `useHookName_scenario_expectedOutcome`
|
|
79
|
-
- **Consistent Pattern:** Always include what's being tested, the scenario, and expected result
|
|
80
|
-
|
|
81
|
-
## React-Specific Test Data Management
|
|
82
|
-
|
|
83
|
-
- **Component Props:** Use realistic props that match production data
|
|
84
|
-
- **Mock Data:** Create mock data that represents actual API responses
|
|
85
|
-
- **User Events:** Simulate realistic user interactions (clicks, typing, navigation)
|
|
86
|
-
- **Async Operations:** Properly test loading states and async data fetching
|
|
87
|
-
- **Temporary File Cleanup:** Clean up all temporary test files, screenshots, and debug outputs after test execution
|
|
88
|
-
- **Mock Cleanup:** Properly reset mocks between tests to avoid test pollution
|
|
89
|
-
|
|
90
|
-
## Test File Hygiene
|
|
91
|
-
|
|
92
|
-
- **No Orphaned Files:** Remove temporary test files created during debugging or development
|
|
93
|
-
- **Debug Output Cleanup:** Remove console output statements and debug files before committing
|
|
94
|
-
- **Test Artifact Management:** Ensure test screenshots, coverage reports, and logs are properly managed
|
|
95
|
-
- **Resource Management:** Properly dispose of DOM elements, event listeners, and other test resources
|
|
96
|
-
- **Documentation Updates:** Remove temporary test documentation and move useful content to proper locations
|
|
97
|
-
|
|
98
|
-
## React Component Testing Patterns
|
|
99
|
-
|
|
100
|
-
### Component Unit Tests
|
|
101
|
-
|
|
102
|
-
- **Render Testing:** Verify components render without crashing
|
|
103
|
-
- **Props Testing:** Test component behavior with different prop combinations
|
|
104
|
-
- **State Testing:** Test component state changes and updates
|
|
105
|
-
- **Event Testing:** Test user interaction handling
|
|
106
|
-
- **Snapshot Testing:** Maintain component structure consistency
|
|
107
|
-
|
|
108
|
-
### Custom Hook Testing
|
|
109
|
-
|
|
110
|
-
- **Hook Logic:** Test hook functionality in isolation
|
|
111
|
-
- **State Management:** Test hook state updates and side effects
|
|
112
|
-
- **Dependencies:** Test hook behavior with different dependencies
|
|
113
|
-
- **Error Handling:** Test hook error scenarios and recovery
|
|
114
|
-
|
|
115
|
-
### Integration Testing
|
|
116
|
-
|
|
117
|
-
- **Component Interaction:** Test how components work together
|
|
118
|
-
- **Data Flow:** Test data passing between parent and child components
|
|
119
|
-
- **Context Providers:** Test components within context providers
|
|
120
|
-
- **Router Integration:** Test routing and navigation behavior
|
|
121
|
-
|
|
122
|
-
### End-to-End Testing
|
|
123
|
-
|
|
124
|
-
- **User Workflows:** Test complete user journeys through the application
|
|
125
|
-
- **Cross-Browser:** Test functionality across different browsers
|
|
126
|
-
- **Responsive Design:** Test application behavior on different screen sizes
|
|
127
|
-
- **Performance:** Test application performance under load
|
|
128
|
-
|
|
129
|
-
## Common React Testing Anti-Patterns to Avoid
|
|
130
|
-
|
|
131
|
-
- **Testing Implementation Details:** Focus on user behavior, not internal state
|
|
132
|
-
- **Shallow Rendering:** Prefer full rendering with React Testing Library
|
|
133
|
-
- **Overmocking:** Mock only external dependencies, not internal components
|
|
134
|
-
- **Snapshot Overuse:** Use snapshots sparingly for UI consistency checks
|
|
135
|
-
- **Ignoring Accessibility:** Always test for accessibility compliance
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "typescript",
|
|
3
|
-
"description": "Shared TypeScript instructions for Node.js and React projects",
|
|
4
|
-
"prompts": [],
|
|
5
|
-
"vscodeSettings": {
|
|
6
|
-
"github.copilot.chat.codeGeneration.useInstructionFiles": true,
|
|
7
|
-
"chat.promptFiles": true,
|
|
8
|
-
"typescript.preferences.inlayHints.parameterNames.enabled": "all",
|
|
9
|
-
"typescript.preferences.inlayHints.variableTypes.enabled": true,
|
|
10
|
-
"editor.formatOnSave": true,
|
|
11
|
-
"editor.codeActionsOnSave": {
|
|
12
|
-
"source.organizeImports": true,
|
|
13
|
-
"source.fixAll.eslint": true
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
@@ -1,368 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: 'TypeScript/Node.js coding standards and conventions'
|
|
3
|
-
applyTo: '**/*.ts'
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# TypeScript/Node.js Coding Standards
|
|
7
|
-
|
|
8
|
-
## Language and Framework Preferences
|
|
9
|
-
|
|
10
|
-
- **Primary Language:** TypeScript for all code files
|
|
11
|
-
- **Code Style:** Follow project's ESLint/Prettier configuration
|
|
12
|
-
- **Target Compatibility:** Node.js 18+, TypeScript 4.9+
|
|
13
|
-
- **Module System:** ES modules (import/export)
|
|
14
|
-
|
|
15
|
-
## Code Quality Guidelines
|
|
16
|
-
|
|
17
|
-
- **Type Safety:** Use strict TypeScript configuration with `strict: true`
|
|
18
|
-
- **Type Annotations:** Explicit types for function parameters and return values
|
|
19
|
-
- **Interface Design:** Prefer interfaces over type aliases for object shapes
|
|
20
|
-
- **Generic Constraints:** Use generic constraints to ensure type safety
|
|
21
|
-
- **Null Safety:** Use strict null checks and optional chaining
|
|
22
|
-
|
|
23
|
-
## Naming Conventions
|
|
24
|
-
|
|
25
|
-
- **Files:** Use kebab-case for file names (e.g., `user-service.ts`)
|
|
26
|
-
- **Classes:** PascalCase (e.g., `UserService`, `DatabaseConnection`)
|
|
27
|
-
- **Functions/Methods:** camelCase (e.g., `getUserById`, `validateInput`)
|
|
28
|
-
- **Variables:** camelCase (e.g., `userId`, `isValid`)
|
|
29
|
-
- **Constants:** SCREAMING_SNAKE_CASE (e.g., `MAX_RETRY_ATTEMPTS`)
|
|
30
|
-
- **Interfaces:** PascalCase with 'I' prefix (e.g., `IUserRepository`)
|
|
31
|
-
- **Types:** PascalCase (e.g., `UserData`, `ConfigOptions`)
|
|
32
|
-
- **Enums:** PascalCase (e.g., `UserRole`, `HttpStatus`)
|
|
33
|
-
|
|
34
|
-
## TypeScript-Specific Best Practices
|
|
35
|
-
|
|
36
|
-
### Type Definitions
|
|
37
|
-
|
|
38
|
-
```typescript
|
|
39
|
-
// ✅ Good: Explicit interface definitions
|
|
40
|
-
interface UserData {
|
|
41
|
-
id: string;
|
|
42
|
-
name: string;
|
|
43
|
-
email: string;
|
|
44
|
-
createdAt: Date;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// ✅ Good: Generic constraints
|
|
48
|
-
interface Repository<T extends { id: string }> {
|
|
49
|
-
findById(id: string): Promise<T | null>;
|
|
50
|
-
save(entity: T): Promise<T>;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// ❌ Bad: Using 'any' type
|
|
54
|
-
const userData: any = getUserData();
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### Error Handling
|
|
58
|
-
|
|
59
|
-
```typescript
|
|
60
|
-
// ✅ Good: Typed error handling
|
|
61
|
-
class ValidationError extends Error {
|
|
62
|
-
constructor(
|
|
63
|
-
message: string,
|
|
64
|
-
public field: string,
|
|
65
|
-
public code: string
|
|
66
|
-
) {
|
|
67
|
-
super(message);
|
|
68
|
-
this.name = 'ValidationError';
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// ✅ Good: Result pattern for error handling
|
|
73
|
-
type Result<T, E = Error> =
|
|
74
|
-
| { success: true; data: T }
|
|
75
|
-
| { success: false; error: E };
|
|
76
|
-
|
|
77
|
-
async function safeOperation(): Promise<Result<UserData>> {
|
|
78
|
-
try {
|
|
79
|
-
const data = await fetchUserData();
|
|
80
|
-
return { success: true, data };
|
|
81
|
-
} catch (error) {
|
|
82
|
-
return { success: false, error: error as Error };
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### Async/Await Patterns
|
|
88
|
-
|
|
89
|
-
```typescript
|
|
90
|
-
// ✅ Good: Proper async/await usage
|
|
91
|
-
async function processUsers(userIds: string[]): Promise<UserData[]> {
|
|
92
|
-
const users = await Promise.all(
|
|
93
|
-
userIds.map((id) => userService.findById(id))
|
|
94
|
-
);
|
|
95
|
-
return users.filter((user): user is UserData => user !== null);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// ❌ Bad: Mixing promises and async/await
|
|
99
|
-
async function badExample() {
|
|
100
|
-
return someAsyncOperation().then((result) => {
|
|
101
|
-
return processResult(result);
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### Module Organization
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
// ✅ Good: Barrel exports in index.ts
|
|
110
|
-
export { UserService } from './user-service';
|
|
111
|
-
export { DatabaseConnection } from './database-connection';
|
|
112
|
-
export type { UserData, CreateUserRequest } from './types';
|
|
113
|
-
|
|
114
|
-
// ✅ Good: Single responsibility per file
|
|
115
|
-
// user-service.ts
|
|
116
|
-
export class UserService {
|
|
117
|
-
constructor(private repository: IUserRepository) {}
|
|
118
|
-
|
|
119
|
-
async createUser(data: CreateUserRequest): Promise<UserData> {
|
|
120
|
-
// Implementation
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
## Node.js-Specific Guidelines
|
|
126
|
-
|
|
127
|
-
### File System Operations
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
// ✅ Good: Async file operations with proper error handling
|
|
131
|
-
import { promises as fs } from 'fs';
|
|
132
|
-
import { join } from 'path';
|
|
133
|
-
|
|
134
|
-
async function readConfigFile(
|
|
135
|
-
filename: string
|
|
136
|
-
): Promise<Record<string, unknown>> {
|
|
137
|
-
try {
|
|
138
|
-
const configPath = join(process.cwd(), 'config', filename);
|
|
139
|
-
const content = await fs.readFile(configPath, 'utf-8');
|
|
140
|
-
return JSON.parse(content);
|
|
141
|
-
} catch (error) {
|
|
142
|
-
throw new Error(`Failed to read config file ${filename}: ${error.message}`);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### Environment Configuration
|
|
148
|
-
|
|
149
|
-
```typescript
|
|
150
|
-
// ✅ Good: Type-safe environment variables
|
|
151
|
-
interface EnvironmentConfig {
|
|
152
|
-
port: number;
|
|
153
|
-
databaseUrl: string;
|
|
154
|
-
nodeEnv: 'development' | 'production' | 'test';
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
function getEnvironmentConfig(): EnvironmentConfig {
|
|
158
|
-
const port = parseInt(process.env.PORT || '3000', 10);
|
|
159
|
-
const databaseUrl = process.env.DATABASE_URL;
|
|
160
|
-
const nodeEnv = process.env.NODE_ENV as EnvironmentConfig['nodeEnv'];
|
|
161
|
-
|
|
162
|
-
if (!databaseUrl) {
|
|
163
|
-
throw new Error('DATABASE_URL environment variable is required');
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return { port, databaseUrl, nodeEnv: nodeEnv || 'development' };
|
|
167
|
-
}
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
### Logging and Debugging
|
|
171
|
-
|
|
172
|
-
```typescript
|
|
173
|
-
// ✅ Good: Structured logging
|
|
174
|
-
interface LogContext {
|
|
175
|
-
userId?: string;
|
|
176
|
-
requestId?: string;
|
|
177
|
-
operation: string;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
class Logger {
|
|
181
|
-
info(message: string, context: LogContext): void {
|
|
182
|
-
console.log(
|
|
183
|
-
JSON.stringify({
|
|
184
|
-
level: 'info',
|
|
185
|
-
message,
|
|
186
|
-
timestamp: new Date().toISOString(),
|
|
187
|
-
...context,
|
|
188
|
-
})
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
error(message: string, error: Error, context: LogContext): void {
|
|
193
|
-
console.error(
|
|
194
|
-
JSON.stringify({
|
|
195
|
-
level: 'error',
|
|
196
|
-
message,
|
|
197
|
-
error: error.message,
|
|
198
|
-
stack: error.stack,
|
|
199
|
-
timestamp: new Date().toISOString(),
|
|
200
|
-
...context,
|
|
201
|
-
})
|
|
202
|
-
);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
## Performance Considerations
|
|
208
|
-
|
|
209
|
-
### Memory Management
|
|
210
|
-
|
|
211
|
-
```typescript
|
|
212
|
-
// ✅ Good: Streaming large data sets
|
|
213
|
-
import { Transform } from 'stream';
|
|
214
|
-
|
|
215
|
-
class DataProcessor extends Transform {
|
|
216
|
-
_transform(
|
|
217
|
-
chunk: any,
|
|
218
|
-
encoding: BufferEncoding,
|
|
219
|
-
callback: TransformCallback
|
|
220
|
-
) {
|
|
221
|
-
// Process chunk by chunk instead of loading everything into memory
|
|
222
|
-
const processed = this.processChunk(chunk);
|
|
223
|
-
callback(null, processed);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// ✅ Good: Cleaning up resources
|
|
228
|
-
class DatabaseConnection {
|
|
229
|
-
private connection: Connection | null = null;
|
|
230
|
-
|
|
231
|
-
async connect(): Promise<void> {
|
|
232
|
-
this.connection = await createConnection();
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
async disconnect(): Promise<void> {
|
|
236
|
-
if (this.connection) {
|
|
237
|
-
await this.connection.close();
|
|
238
|
-
this.connection = null;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
### Caching Strategies
|
|
245
|
-
|
|
246
|
-
```typescript
|
|
247
|
-
// ✅ Good: Simple in-memory cache with TTL
|
|
248
|
-
class CacheService<T> {
|
|
249
|
-
private cache = new Map<string, { data: T; expires: number }>();
|
|
250
|
-
|
|
251
|
-
set(key: string, data: T, ttlMs: number): void {
|
|
252
|
-
this.cache.set(key, {
|
|
253
|
-
data,
|
|
254
|
-
expires: Date.now() + ttlMs,
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
get(key: string): T | null {
|
|
259
|
-
const entry = this.cache.get(key);
|
|
260
|
-
if (!entry || entry.expires < Date.now()) {
|
|
261
|
-
this.cache.delete(key);
|
|
262
|
-
return null;
|
|
263
|
-
}
|
|
264
|
-
return entry.data;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
## Testing Patterns
|
|
270
|
-
|
|
271
|
-
### Unit Testing with Jest
|
|
272
|
-
|
|
273
|
-
```typescript
|
|
274
|
-
// ✅ Good: Type-safe mocking
|
|
275
|
-
interface MockUserRepository extends IUserRepository {
|
|
276
|
-
findById: jest.MockedFunction<IUserRepository['findById']>;
|
|
277
|
-
save: jest.MockedFunction<IUserRepository['save']>;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
describe('UserService', () => {
|
|
281
|
-
let userService: UserService;
|
|
282
|
-
let mockRepository: MockUserRepository;
|
|
283
|
-
|
|
284
|
-
beforeEach(() => {
|
|
285
|
-
mockRepository = {
|
|
286
|
-
findById: jest.fn(),
|
|
287
|
-
save: jest.fn(),
|
|
288
|
-
};
|
|
289
|
-
userService = new UserService(mockRepository);
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
it('should return user when found', async () => {
|
|
293
|
-
// Arrange
|
|
294
|
-
const userData: UserData = {
|
|
295
|
-
id: '123',
|
|
296
|
-
name: 'John Doe',
|
|
297
|
-
email: 'john@example.com',
|
|
298
|
-
createdAt: new Date(),
|
|
299
|
-
};
|
|
300
|
-
mockRepository.findById.mockResolvedValue(userData);
|
|
301
|
-
|
|
302
|
-
// Act
|
|
303
|
-
const result = await userService.getUserById('123');
|
|
304
|
-
|
|
305
|
-
// Assert
|
|
306
|
-
expect(result).toEqual(userData);
|
|
307
|
-
expect(mockRepository.findById).toHaveBeenCalledWith('123');
|
|
308
|
-
});
|
|
309
|
-
});
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
## Security Best Practices
|
|
313
|
-
|
|
314
|
-
### Input Validation
|
|
315
|
-
|
|
316
|
-
```typescript
|
|
317
|
-
import { z } from 'zod';
|
|
318
|
-
|
|
319
|
-
// ✅ Good: Schema-based validation
|
|
320
|
-
const CreateUserSchema = z.object({
|
|
321
|
-
name: z.string().min(1).max(100),
|
|
322
|
-
email: z.string().email(),
|
|
323
|
-
age: z.number().int().min(0).max(150),
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
type CreateUserRequest = z.infer<typeof CreateUserSchema>;
|
|
327
|
-
|
|
328
|
-
function validateCreateUserRequest(data: unknown): CreateUserRequest {
|
|
329
|
-
try {
|
|
330
|
-
return CreateUserSchema.parse(data);
|
|
331
|
-
} catch (error) {
|
|
332
|
-
throw new ValidationError(
|
|
333
|
-
'Invalid user data',
|
|
334
|
-
'request',
|
|
335
|
-
'VALIDATION_FAILED'
|
|
336
|
-
);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
### SQL Injection Prevention
|
|
342
|
-
|
|
343
|
-
```typescript
|
|
344
|
-
// ✅ Good: Parameterized queries
|
|
345
|
-
async function getUserByEmail(email: string): Promise<UserData | null> {
|
|
346
|
-
const query = 'SELECT * FROM users WHERE email = $1';
|
|
347
|
-
const result = await database.query(query, [email]);
|
|
348
|
-
return result.rows[0] || null;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// ❌ Bad: String concatenation
|
|
352
|
-
async function badGetUserByEmail(email: string): Promise<UserData | null> {
|
|
353
|
-
const query = `SELECT * FROM users WHERE email = '${email}'`;
|
|
354
|
-
const result = await database.query(query);
|
|
355
|
-
return result.rows[0] || null;
|
|
356
|
-
}
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
## Common TypeScript Anti-Patterns to Avoid
|
|
360
|
-
|
|
361
|
-
- **Using `any` type:** Always prefer specific types or `unknown`
|
|
362
|
-
- **Ignoring compiler errors:** Address TypeScript errors, don't suppress them
|
|
363
|
-
- **Overusing `as` assertions:** Use type guards and proper type narrowing
|
|
364
|
-
- **Not defining return types:** Always specify return types for functions
|
|
365
|
-
- **Mixing CommonJS and ES modules:** Stick to ES modules consistently
|
|
366
|
-
- **Not using strict mode:** Always enable strict TypeScript configuration
|
|
367
|
-
- **Mutating props or parameters:** Prefer immutable patterns
|
|
368
|
-
- **Not handling promise rejections:** Always handle async operation failures
|