trinity-method-sdk 2.1.0 → 2.2.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 +728 -467
- package/README.md +550 -539
- package/dist/cli/commands/deploy/ci-cd.d.ts +4 -3
- package/dist/cli/commands/deploy/ci-cd.js +10 -9
- package/dist/cli/commands/deploy/configuration.js +10 -11
- package/dist/cli/commands/deploy/directories.js +13 -14
- package/dist/cli/commands/deploy/gitignore.js +3 -4
- package/dist/cli/commands/deploy/index.d.ts +1 -1
- package/dist/cli/commands/deploy/index.js +6 -2
- package/dist/cli/commands/deploy/knowledge-base.js +2 -2
- package/dist/cli/commands/deploy/pre-flight.js +1 -1
- package/dist/cli/commands/deploy/root-files.js +2 -17
- package/dist/cli/commands/deploy/summary.js +3 -3
- package/dist/cli/commands/deploy/templates.js +5 -5
- package/dist/cli/commands/update/backup.js +6 -12
- package/dist/cli/commands/update/index.js +15 -1
- package/dist/cli/commands/update/knowledge-base.js +1 -1
- package/dist/cli/commands/update/migration.d.ts +31 -0
- package/dist/cli/commands/update/migration.js +130 -0
- package/dist/cli/commands/update/pre-flight.d.ts +7 -2
- package/dist/cli/commands/update/pre-flight.js +21 -20
- package/dist/cli/commands/update/summary.js +11 -5
- package/dist/cli/commands/update/templates.js +1 -1
- package/dist/cli/commands/update/types.d.ts +2 -0
- package/dist/cli/commands/update/verification.js +5 -5
- package/dist/cli/commands/update/version.js +6 -4
- package/dist/cli/utils/deploy-ci.d.ts +3 -2
- package/dist/cli/utils/deploy-ci.js +24 -24
- package/dist/cli/utils/deploy-linting.js +100 -5
- package/dist/cli/utils/error-classes.d.ts +2 -2
- package/dist/cli/utils/linting-tools.js +14 -6
- package/dist/cli/utils/template-processor.js +1 -3
- package/dist/templates/.claude/EMPLOYEE-DIRECTORY.md.template +16 -22
- package/dist/templates/.claude/agents/aj-team/apo-documentation-specialist.md.template +7 -7
- package/dist/templates/.claude/agents/aj-team/bas-quality-gate.md.template +8 -8
- package/dist/templates/.claude/agents/aj-team/dra-code-reviewer.md.template +3 -3
- package/dist/templates/.claude/agents/aj-team/kil-task-executor.md.template +6 -6
- package/dist/templates/.claude/agents/audit/juno-auditor.md.template +39 -40
- package/dist/templates/.claude/agents/deployment/ein-cicd.md.template +56 -159
- package/dist/templates/.claude/agents/deployment/ino-context.md.template +21 -21
- package/dist/templates/.claude/agents/deployment/tan-structure.md.template +28 -29
- package/dist/templates/.claude/agents/deployment/zen-knowledge.md.template +22 -23
- package/dist/templates/.claude/agents/leadership/aj-maestro.md.template +6 -6
- package/dist/templates/.claude/agents/leadership/aly-cto.md.template +17 -18
- package/dist/templates/.claude/agents/planning/eus-decomposer.md.template +4 -4
- package/dist/templates/.claude/agents/planning/mon-requirements.md.template +4 -4
- package/dist/templates/.claude/agents/planning/ror-design.md.template +4 -4
- package/dist/templates/.claude/agents/planning/tra-planner.md.template +4 -4
- package/dist/templates/.claude/commands/execution/trinity-audit.md.template +9 -9
- package/dist/templates/.claude/commands/execution/trinity-breakdown.md.template +535 -0
- package/dist/templates/.claude/commands/execution/trinity-orchestrate.md.template +43 -43
- package/dist/templates/.claude/commands/infrastructure/trinity-init.md.template +20 -43
- package/dist/templates/.claude/commands/investigation/trinity-create-investigation.md.template +5 -5
- package/dist/templates/.claude/commands/investigation/trinity-investigate-templates.md.template +10 -10
- package/dist/templates/.claude/commands/investigation/trinity-plan-investigation.md.template +1 -1
- package/dist/templates/.claude/commands/maintenance/trinity-changelog.md.template +4 -4
- package/dist/templates/.claude/commands/maintenance/trinity-docs-update.md.template +10 -10
- package/dist/templates/.claude/commands/maintenance/trinity-docs.md.template +62 -62
- package/dist/templates/.claude/commands/maintenance/trinity-readme.md.template +16 -16
- package/dist/templates/.claude/commands/session/trinity-continue.md.template +22 -22
- package/dist/templates/.claude/commands/session/trinity-end.md.template +22 -22
- package/dist/templates/.claude/commands/session/trinity-start.md.template +1 -2
- package/dist/templates/.claude/commands/utility/trinity-agents.md.template +3 -6
- package/dist/templates/.claude/commands/utility/trinity-verify.md.template +48 -54
- package/dist/templates/.claude/commands/utility/trinity-workorder.md.template +5 -5
- package/dist/templates/ci/ci.yml.template +2 -2
- package/dist/templates/root/CLAUDE.md.template +9 -9
- package/dist/templates/root/linting/nodejs/.husky-pre-commit.template +5 -0
- package/dist/templates/source/base-CLAUDE.md.template +310 -310
- package/dist/templates/source/flutter-CLAUDE.md.template +593 -593
- package/dist/templates/source/nodejs-CLAUDE.md.template +531 -531
- package/dist/templates/source/python-CLAUDE.md.template +510 -510
- package/dist/templates/source/react-CLAUDE.md.template +513 -513
- package/dist/templates/source/rust-CLAUDE.md.template +653 -653
- package/dist/templates/trinity/CLAUDE.md.template +14 -14
- package/dist/templates/trinity/knowledge-base/ARCHITECTURE.md.template +4 -4
- package/dist/templates/trinity/knowledge-base/ISSUES.md.template +8 -8
- package/dist/templates/trinity/knowledge-base/Technical-Debt.md.template +1 -3
- package/dist/templates/trinity/knowledge-base/To-do.md.template +1 -1
- package/dist/templates/trinity/knowledge-base/Trinity.md.template +5 -5
- package/dist/templates/trinity/templates/documentation/configuration/env-example-generator.md.template +1 -1
- package/dist/templates/trinity/templates/documentation/processes/error-handling-protocol.md.template +2 -2
- package/dist/templates/trinity/templates/documentation/reports/apo-docs-update-checklist.md.template +7 -7
- package/dist/templates/trinity/templates/documentation/reports/juno-docs-update-checklist.md.template +4 -4
- package/dist/templates/trinity/templates/documentation/reports/juno-internal-report.md.template +10 -10
- package/dist/templates/trinity/templates/investigations/bug.md.template +14 -14
- package/dist/templates/trinity/templates/investigations/feature.md.template +14 -14
- package/dist/templates/trinity/templates/investigations/performance.md.template +14 -14
- package/dist/templates/trinity/templates/investigations/security.md.template +14 -14
- package/dist/templates/trinity/templates/investigations/technical.md.template +14 -14
- package/dist/templates/trinity/templates/work-orders/ANALYSIS-TEMPLATE.md.template +10 -10
- package/dist/templates/trinity/templates/work-orders/AUDIT-TEMPLATE.md.template +10 -10
- package/dist/templates/trinity/templates/work-orders/IMPLEMENTATION-TEMPLATE.md.template +10 -10
- package/dist/templates/trinity/templates/work-orders/INVESTIGATION-TEMPLATE.md.template +10 -10
- package/dist/templates/trinity/templates/work-orders/PATTERN-TEMPLATE.md.template +10 -10
- package/dist/templates/trinity/templates/work-orders/VERIFICATION-TEMPLATE.md.template +10 -10
- package/package.json +99 -94
- package/dist/templates/.claude/agents/leadership/aj-cc.md.template +0 -467
- package/dist/templates/ci/cd.yml.template +0 -175
- package/dist/templates/ci/github-actions.yml +0 -86
- package/dist/templates/root/TRINITY.md.template +0 -52
|
@@ -1,513 +1,513 @@
|
|
|
1
|
-
# CLAUDE.md - React Technology-Specific Rules
|
|
2
|
-
## {{PROJECT_NAME}} - React Implementation
|
|
3
|
-
|
|
4
|
-
**Framework:** React
|
|
5
|
-
**Language:** JavaScript/TypeScript
|
|
6
|
-
**Source Directory:** {{SOURCE_DIR}}
|
|
7
|
-
**Build Tool:** Vite/Webpack/Create React App
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## Technology Stack Behavioral Modifications
|
|
12
|
-
|
|
13
|
-
### React-Specific Requirements
|
|
14
|
-
- **Component Patterns**: Use functional components with hooks
|
|
15
|
-
- **State Management**: Implement appropriate state solution (Context, Redux, Zustand, Recoil)
|
|
16
|
-
- **Performance Optimization**: Use React.memo, useMemo, useCallback appropriately
|
|
17
|
-
- **Code Splitting**: Implement lazy loading for route-based code splitting
|
|
18
|
-
- **TypeScript**: Prefer TypeScript for type safety
|
|
19
|
-
|
|
20
|
-
### Modern React Practices
|
|
21
|
-
- **Hooks**: Use built-in and custom hooks for logic reuse
|
|
22
|
-
- **Composition**: Favor composition over inheritance
|
|
23
|
-
- **Pure Components**: Keep components pure and predictable
|
|
24
|
-
- **Error Boundaries**: Implement error boundaries for graceful failures
|
|
25
|
-
- **Suspense**: Use Suspense for async operations
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## Technology Debugging Standards
|
|
30
|
-
|
|
31
|
-
### React Debugging Framework
|
|
32
|
-
```javascript
|
|
33
|
-
// Standard debugging format for React applications
|
|
34
|
-
const createDebugLogger = (componentName) => {
|
|
35
|
-
return {
|
|
36
|
-
render: (props, state) => {
|
|
37
|
-
if (process.env.NODE_ENV === 'development') {
|
|
38
|
-
console.log(`[RENDER] ${componentName}`, {
|
|
39
|
-
props: props,
|
|
40
|
-
state: state,
|
|
41
|
-
timestamp: new Date().toISOString()
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
effect: (effectName, dependencies) => {
|
|
46
|
-
if (process.env.NODE_ENV === 'development') {
|
|
47
|
-
console.log(`[EFFECT] ${componentName}.${effectName}`, {
|
|
48
|
-
dependencies: dependencies,
|
|
49
|
-
timestamp: new Date().toISOString()
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
error: (error, errorInfo) => {
|
|
54
|
-
console.error(`[ERROR] ${componentName}`, {
|
|
55
|
-
error: error.message,
|
|
56
|
-
componentStack: errorInfo?.componentStack,
|
|
57
|
-
timestamp: new Date().toISOString()
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
// Usage in component
|
|
64
|
-
const UserProfile = ({ userId }) => {
|
|
65
|
-
const logger = createDebugLogger('UserProfile');
|
|
66
|
-
|
|
67
|
-
useEffect(() => {
|
|
68
|
-
logger.effect('fetchUser', [userId]);
|
|
69
|
-
|
|
70
|
-
fetchUser(userId)
|
|
71
|
-
.then(user => logger.render({ userId }, user))
|
|
72
|
-
.catch(error => logger.error(error, {}));
|
|
73
|
-
}, [userId]);
|
|
74
|
-
|
|
75
|
-
logger.render({ userId }, null);
|
|
76
|
-
|
|
77
|
-
return <div>Profile</div>;
|
|
78
|
-
};
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### React DevTools Integration
|
|
82
|
-
```javascript
|
|
83
|
-
// Custom hooks with DevTools debugging
|
|
84
|
-
function useDebugValue(value, format = (v) => v) {
|
|
85
|
-
useDebugValue(format(value));
|
|
86
|
-
return value;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Usage
|
|
90
|
-
function useUser(userId) {
|
|
91
|
-
const user = useSWR(`/api/users/${userId}`);
|
|
92
|
-
useDebugValue(user, u => u.data ? `User: ${u.data.name}` : 'Loading...');
|
|
93
|
-
return user;
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
---
|
|
98
|
-
|
|
99
|
-
## Performance Optimization Rules
|
|
100
|
-
|
|
101
|
-
### React Performance Monitoring
|
|
102
|
-
```javascript
|
|
103
|
-
// Performance measurement for components
|
|
104
|
-
import { Profiler } from 'react';
|
|
105
|
-
|
|
106
|
-
function onRenderCallback(
|
|
107
|
-
id, // the "id" prop of the Profiler tree that has just committed
|
|
108
|
-
phase, // either "mount" or "update"
|
|
109
|
-
actualDuration, // time spent rendering the committed update
|
|
110
|
-
baseDuration, // estimated time to render the entire subtree
|
|
111
|
-
startTime, // when React began rendering this update
|
|
112
|
-
commitTime // when React committed this update
|
|
113
|
-
) {
|
|
114
|
-
console.log('[PERF]', {
|
|
115
|
-
component: id,
|
|
116
|
-
phase: phase,
|
|
117
|
-
actualDuration: `${actualDuration.toFixed(2)}ms`,
|
|
118
|
-
baseDuration: `${baseDuration.toFixed(2)}ms`,
|
|
119
|
-
timestamp: new Date(commitTime).toISOString()
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Usage
|
|
124
|
-
<Profiler id="UserList" onRender={onRenderCallback}>
|
|
125
|
-
<UserList />
|
|
126
|
-
</Profiler>
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### Memoization Patterns
|
|
130
|
-
```javascript
|
|
131
|
-
// Optimize expensive computations
|
|
132
|
-
const ExpensiveComponent = ({ data }) => {
|
|
133
|
-
const processedData = useMemo(() => {
|
|
134
|
-
console.log('[MEMO] Processing data...');
|
|
135
|
-
return expensiveOperation(data);
|
|
136
|
-
}, [data]);
|
|
137
|
-
|
|
138
|
-
const handleClick = useCallback(() => {
|
|
139
|
-
console.log('[CALLBACK] Handler executed');
|
|
140
|
-
// Handle click
|
|
141
|
-
}, []);
|
|
142
|
-
|
|
143
|
-
return <div onClick={handleClick}>{processedData}</div>;
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
// Memoize entire component
|
|
147
|
-
export default React.memo(ExpensiveComponent);
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
## Security Best Practices
|
|
153
|
-
|
|
154
|
-
### XSS Prevention
|
|
155
|
-
```javascript
|
|
156
|
-
// Safe HTML rendering
|
|
157
|
-
import DOMPurify from 'dompurify';
|
|
158
|
-
|
|
159
|
-
function SafeHTML({ html }) {
|
|
160
|
-
const sanitizedHTML = DOMPurify.sanitize(html);
|
|
161
|
-
|
|
162
|
-
return <div dangerouslySetInnerHTML={{ __html: sanitizedHTML }} />;
|
|
163
|
-
}
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### Input Validation
|
|
167
|
-
```javascript
|
|
168
|
-
// Form validation patterns
|
|
169
|
-
const validateInput = (value, rules) => {
|
|
170
|
-
const errors = [];
|
|
171
|
-
|
|
172
|
-
if (rules.required && !value) {
|
|
173
|
-
errors.push('Field is required');
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (rules.email && value && !/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(value)) {
|
|
177
|
-
errors.push('Invalid email format');
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (rules.minLength && value && value.length < rules.minLength) {
|
|
181
|
-
errors.push(`Minimum length is ${rules.minLength}`);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
return errors;
|
|
185
|
-
};
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
---
|
|
189
|
-
|
|
190
|
-
## Testing Requirements
|
|
191
|
-
|
|
192
|
-
### Jest + React Testing Library
|
|
193
|
-
```javascript
|
|
194
|
-
// Component testing
|
|
195
|
-
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
196
|
-
import '@testing-library/jest-dom';
|
|
197
|
-
import UserProfile from './UserProfile';
|
|
198
|
-
|
|
199
|
-
describe('UserProfile', () => {
|
|
200
|
-
it('renders user information', async () => {
|
|
201
|
-
render(<UserProfile userId="123" />);
|
|
202
|
-
|
|
203
|
-
await waitFor(() => {
|
|
204
|
-
expect(screen.getByText(/John Doe/i)).toBeInTheDocument();
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
it('handles user interaction', async () => {
|
|
209
|
-
const handleClick = jest.fn();
|
|
210
|
-
render(<UserProfile userId="123" onEdit={handleClick} />);
|
|
211
|
-
|
|
212
|
-
fireEvent.click(screen.getByRole('button', { name: /edit/i }));
|
|
213
|
-
|
|
214
|
-
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
215
|
-
});
|
|
216
|
-
});
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### Hook Testing
|
|
220
|
-
```javascript
|
|
221
|
-
// Custom hook testing
|
|
222
|
-
import { renderHook, act } from '@testing-library/react';
|
|
223
|
-
import { useCounter } from './useCounter';
|
|
224
|
-
|
|
225
|
-
describe('useCounter', () => {
|
|
226
|
-
it('increments counter', () => {
|
|
227
|
-
const { result } = renderHook(() => useCounter(0));
|
|
228
|
-
|
|
229
|
-
act(() => {
|
|
230
|
-
result.current.increment();
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
expect(result.current.count).toBe(1);
|
|
234
|
-
});
|
|
235
|
-
});
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
---
|
|
239
|
-
|
|
240
|
-
## Framework Best Practices
|
|
241
|
-
|
|
242
|
-
### Component Structure
|
|
243
|
-
```javascript
|
|
244
|
-
// Standard component structure
|
|
245
|
-
import React, { useState, useEffect, useCallback } from 'react';
|
|
246
|
-
import PropTypes from 'prop-types';
|
|
247
|
-
|
|
248
|
-
const UserProfile = ({ userId, onUpdate }) => {
|
|
249
|
-
// State declarations
|
|
250
|
-
const [user, setUser] = useState(null);
|
|
251
|
-
const [loading, setLoading] = useState(true);
|
|
252
|
-
const [error, setError] = useState(null);
|
|
253
|
-
|
|
254
|
-
// Effects
|
|
255
|
-
useEffect(() => {
|
|
256
|
-
fetchUser(userId)
|
|
257
|
-
.then(setUser)
|
|
258
|
-
.catch(setError)
|
|
259
|
-
.finally(() => setLoading(false));
|
|
260
|
-
}, [userId]);
|
|
261
|
-
|
|
262
|
-
// Callbacks
|
|
263
|
-
const handleUpdate = useCallback(() => {
|
|
264
|
-
onUpdate(user);
|
|
265
|
-
}, [user, onUpdate]);
|
|
266
|
-
|
|
267
|
-
// Render logic
|
|
268
|
-
if (loading) return <div>Loading...</div>;
|
|
269
|
-
if (error) return <div>Error: {error.message}</div>;
|
|
270
|
-
|
|
271
|
-
return (
|
|
272
|
-
<div className="user-profile">
|
|
273
|
-
<h1>{user.name}</h1>
|
|
274
|
-
<button onClick={handleUpdate}>Update</button>
|
|
275
|
-
</div>
|
|
276
|
-
);
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
// PropTypes validation
|
|
280
|
-
UserProfile.propTypes = {
|
|
281
|
-
userId: PropTypes.string.isRequired,
|
|
282
|
-
onUpdate: PropTypes.func.isRequired
|
|
283
|
-
};
|
|
284
|
-
|
|
285
|
-
export default UserProfile;
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
### Custom Hooks
|
|
289
|
-
```javascript
|
|
290
|
-
// Reusable custom hook
|
|
291
|
-
function useFetch(url, options = {}) {
|
|
292
|
-
const [data, setData] = useState(null);
|
|
293
|
-
const [loading, setLoading] = useState(true);
|
|
294
|
-
const [error, setError] = useState(null);
|
|
295
|
-
|
|
296
|
-
useEffect(() => {
|
|
297
|
-
console.log('[HOOK] useFetch', { url, options });
|
|
298
|
-
|
|
299
|
-
const abortController = new AbortController();
|
|
300
|
-
|
|
301
|
-
fetch(url, { ...options, signal: abortController.signal })
|
|
302
|
-
.then(res => res.json())
|
|
303
|
-
.then(setData)
|
|
304
|
-
.catch(err => {
|
|
305
|
-
if (err.name !== 'AbortError') {
|
|
306
|
-
setError(err);
|
|
307
|
-
}
|
|
308
|
-
})
|
|
309
|
-
.finally(() => setLoading(false));
|
|
310
|
-
|
|
311
|
-
return () => abortController.abort();
|
|
312
|
-
}, [url, JSON.stringify(options)]);
|
|
313
|
-
|
|
314
|
-
return { data, loading, error };
|
|
315
|
-
}
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
---
|
|
319
|
-
|
|
320
|
-
## Error Handling Patterns
|
|
321
|
-
|
|
322
|
-
### Error Boundaries
|
|
323
|
-
```javascript
|
|
324
|
-
// Error boundary component
|
|
325
|
-
class ErrorBoundary extends React.Component {
|
|
326
|
-
constructor(props) {
|
|
327
|
-
super(props);
|
|
328
|
-
this.state = { hasError: false, error: null };
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
static getDerivedStateFromError(error) {
|
|
332
|
-
return { hasError: true, error };
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
componentDidCatch(error, errorInfo) {
|
|
336
|
-
console.error('[ERROR-BOUNDARY]', {
|
|
337
|
-
error: error.message,
|
|
338
|
-
componentStack: errorInfo.componentStack,
|
|
339
|
-
timestamp: new Date().toISOString()
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
// Report to error tracking service
|
|
343
|
-
// reportError(error, errorInfo);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
render() {
|
|
347
|
-
if (this.state.hasError) {
|
|
348
|
-
return (
|
|
349
|
-
<div className="error-fallback">
|
|
350
|
-
<h1>Something went wrong</h1>
|
|
351
|
-
<details>
|
|
352
|
-
<summary>Error details</summary>
|
|
353
|
-
<pre>{this.state.error?.message}</pre>
|
|
354
|
-
</details>
|
|
355
|
-
</div>
|
|
356
|
-
);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
return this.props.children;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// Usage
|
|
364
|
-
<ErrorBoundary>
|
|
365
|
-
<App />
|
|
366
|
-
</ErrorBoundary>
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
### Async Error Handling
|
|
370
|
-
```javascript
|
|
371
|
-
// Safe async operations
|
|
372
|
-
async function safeAsync(operation, errorHandler) {
|
|
373
|
-
try {
|
|
374
|
-
return await operation();
|
|
375
|
-
} catch (error) {
|
|
376
|
-
console.error('[ASYNC-ERROR]', {
|
|
377
|
-
error: error.message,
|
|
378
|
-
stack: error.stack,
|
|
379
|
-
timestamp: new Date().toISOString()
|
|
380
|
-
});
|
|
381
|
-
|
|
382
|
-
if (errorHandler) {
|
|
383
|
-
return errorHandler(error);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
throw error;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
---
|
|
392
|
-
|
|
393
|
-
## Technology-Specific Command References
|
|
394
|
-
|
|
395
|
-
### Development Commands
|
|
396
|
-
```bash
|
|
397
|
-
# Development
|
|
398
|
-
npm start # Start dev server
|
|
399
|
-
npm run dev # Alternative dev command
|
|
400
|
-
npm run build # Production build
|
|
401
|
-
npm run preview # Preview production build
|
|
402
|
-
|
|
403
|
-
# Type Checking (if TypeScript)
|
|
404
|
-
npm run type-check # Check types
|
|
405
|
-
tsc --noEmit # TypeScript compilation check
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
### Testing Commands
|
|
409
|
-
```bash
|
|
410
|
-
# Testing
|
|
411
|
-
npm test # Run tests
|
|
412
|
-
npm run test:watch # Watch mode
|
|
413
|
-
npm run test:coverage # Generate coverage
|
|
414
|
-
npm run test:debug # Debug tests
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
---
|
|
418
|
-
|
|
419
|
-
## State Management Patterns
|
|
420
|
-
|
|
421
|
-
### Context API
|
|
422
|
-
```javascript
|
|
423
|
-
// Context setup
|
|
424
|
-
const UserContext = React.createContext(null);
|
|
425
|
-
|
|
426
|
-
export const UserProvider = ({ children }) => {
|
|
427
|
-
const [user, setUser] = useState(null);
|
|
428
|
-
|
|
429
|
-
const login = useCallback(async (credentials) => {
|
|
430
|
-
const user = await authService.login(credentials);
|
|
431
|
-
setUser(user);
|
|
432
|
-
}, []);
|
|
433
|
-
|
|
434
|
-
const logout = useCallback(() => {
|
|
435
|
-
setUser(null);
|
|
436
|
-
}, []);
|
|
437
|
-
|
|
438
|
-
const value = useMemo(
|
|
439
|
-
() => ({ user, login, logout }),
|
|
440
|
-
[user, login, logout]
|
|
441
|
-
);
|
|
442
|
-
|
|
443
|
-
return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
|
|
444
|
-
};
|
|
445
|
-
|
|
446
|
-
export const useUser = () => {
|
|
447
|
-
const context = useContext(UserContext);
|
|
448
|
-
if (!context) {
|
|
449
|
-
throw new Error('useUser must be used within UserProvider');
|
|
450
|
-
}
|
|
451
|
-
return context;
|
|
452
|
-
};
|
|
453
|
-
```
|
|
454
|
-
|
|
455
|
-
### Redux (if applicable)
|
|
456
|
-
```javascript
|
|
457
|
-
// Redux slice
|
|
458
|
-
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
|
|
459
|
-
|
|
460
|
-
export const fetchUsers = createAsyncThunk(
|
|
461
|
-
'users/fetchUsers',
|
|
462
|
-
async () => {
|
|
463
|
-
console.log('[REDUX] Fetching users...');
|
|
464
|
-
const response = await api.getUsers();
|
|
465
|
-
return response.data;
|
|
466
|
-
}
|
|
467
|
-
);
|
|
468
|
-
|
|
469
|
-
const usersSlice = createSlice({
|
|
470
|
-
name: 'users',
|
|
471
|
-
initialState: { entities: [], loading: false, error: null },
|
|
472
|
-
reducers: {},
|
|
473
|
-
extraReducers: (builder) => {
|
|
474
|
-
builder
|
|
475
|
-
.addCase(fetchUsers.pending, (state) => {
|
|
476
|
-
state.loading = true;
|
|
477
|
-
})
|
|
478
|
-
.addCase(fetchUsers.fulfilled, (state, action) => {
|
|
479
|
-
state.entities = action.payload;
|
|
480
|
-
state.loading = false;
|
|
481
|
-
})
|
|
482
|
-
.addCase(fetchUsers.rejected, (state, action) => {
|
|
483
|
-
state.error = action.error.message;
|
|
484
|
-
state.loading = false;
|
|
485
|
-
});
|
|
486
|
-
}
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
export default usersSlice.reducer;
|
|
490
|
-
```
|
|
491
|
-
|
|
492
|
-
---
|
|
493
|
-
|
|
494
|
-
## Reference to Parent Context
|
|
495
|
-
|
|
496
|
-
This file extends the Trinity Method protocols defined in
|
|
497
|
-
|
|
498
|
-
- Trinity Method investigation requirements ([
|
|
499
|
-
- Global performance baselines ([
|
|
500
|
-
- Quality gate standards (BAS 6-phase) ([
|
|
501
|
-
- Crisis management protocols ([
|
|
502
|
-
|
|
503
|
-
All React code must implement the debugging frameworks, error handling patterns, and performance monitoring specified in this document.
|
|
504
|
-
|
|
505
|
-
---
|
|
506
|
-
|
|
507
|
-
**Technology Context**: React Implementation
|
|
508
|
-
**Parent References**:
|
|
509
|
-
- `../CLAUDE.md` - Global project requirements
|
|
510
|
-
-
|
|
511
|
-
|
|
512
|
-
**Last Updated**: {{CURRENT_DATE}}
|
|
513
|
-
**Trinity Version**: {{TRINITY_VERSION}}
|
|
1
|
+
# CLAUDE.md - React Technology-Specific Rules
|
|
2
|
+
## {{PROJECT_NAME}} - React Implementation
|
|
3
|
+
|
|
4
|
+
**Framework:** React
|
|
5
|
+
**Language:** JavaScript/TypeScript
|
|
6
|
+
**Source Directory:** {{SOURCE_DIR}}
|
|
7
|
+
**Build Tool:** Vite/Webpack/Create React App
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Technology Stack Behavioral Modifications
|
|
12
|
+
|
|
13
|
+
### React-Specific Requirements
|
|
14
|
+
- **Component Patterns**: Use functional components with hooks
|
|
15
|
+
- **State Management**: Implement appropriate state solution (Context, Redux, Zustand, Recoil)
|
|
16
|
+
- **Performance Optimization**: Use React.memo, useMemo, useCallback appropriately
|
|
17
|
+
- **Code Splitting**: Implement lazy loading for route-based code splitting
|
|
18
|
+
- **TypeScript**: Prefer TypeScript for type safety
|
|
19
|
+
|
|
20
|
+
### Modern React Practices
|
|
21
|
+
- **Hooks**: Use built-in and custom hooks for logic reuse
|
|
22
|
+
- **Composition**: Favor composition over inheritance
|
|
23
|
+
- **Pure Components**: Keep components pure and predictable
|
|
24
|
+
- **Error Boundaries**: Implement error boundaries for graceful failures
|
|
25
|
+
- **Suspense**: Use Suspense for async operations
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Technology Debugging Standards
|
|
30
|
+
|
|
31
|
+
### React Debugging Framework
|
|
32
|
+
```javascript
|
|
33
|
+
// Standard debugging format for React applications
|
|
34
|
+
const createDebugLogger = (componentName) => {
|
|
35
|
+
return {
|
|
36
|
+
render: (props, state) => {
|
|
37
|
+
if (process.env.NODE_ENV === 'development') {
|
|
38
|
+
console.log(`[RENDER] ${componentName}`, {
|
|
39
|
+
props: props,
|
|
40
|
+
state: state,
|
|
41
|
+
timestamp: new Date().toISOString()
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
effect: (effectName, dependencies) => {
|
|
46
|
+
if (process.env.NODE_ENV === 'development') {
|
|
47
|
+
console.log(`[EFFECT] ${componentName}.${effectName}`, {
|
|
48
|
+
dependencies: dependencies,
|
|
49
|
+
timestamp: new Date().toISOString()
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
error: (error, errorInfo) => {
|
|
54
|
+
console.error(`[ERROR] ${componentName}`, {
|
|
55
|
+
error: error.message,
|
|
56
|
+
componentStack: errorInfo?.componentStack,
|
|
57
|
+
timestamp: new Date().toISOString()
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// Usage in component
|
|
64
|
+
const UserProfile = ({ userId }) => {
|
|
65
|
+
const logger = createDebugLogger('UserProfile');
|
|
66
|
+
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
logger.effect('fetchUser', [userId]);
|
|
69
|
+
|
|
70
|
+
fetchUser(userId)
|
|
71
|
+
.then(user => logger.render({ userId }, user))
|
|
72
|
+
.catch(error => logger.error(error, {}));
|
|
73
|
+
}, [userId]);
|
|
74
|
+
|
|
75
|
+
logger.render({ userId }, null);
|
|
76
|
+
|
|
77
|
+
return <div>Profile</div>;
|
|
78
|
+
};
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### React DevTools Integration
|
|
82
|
+
```javascript
|
|
83
|
+
// Custom hooks with DevTools debugging
|
|
84
|
+
function useDebugValue(value, format = (v) => v) {
|
|
85
|
+
useDebugValue(format(value));
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Usage
|
|
90
|
+
function useUser(userId) {
|
|
91
|
+
const user = useSWR(`/api/users/${userId}`);
|
|
92
|
+
useDebugValue(user, u => u.data ? `User: ${u.data.name}` : 'Loading...');
|
|
93
|
+
return user;
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Performance Optimization Rules
|
|
100
|
+
|
|
101
|
+
### React Performance Monitoring
|
|
102
|
+
```javascript
|
|
103
|
+
// Performance measurement for components
|
|
104
|
+
import { Profiler } from 'react';
|
|
105
|
+
|
|
106
|
+
function onRenderCallback(
|
|
107
|
+
id, // the "id" prop of the Profiler tree that has just committed
|
|
108
|
+
phase, // either "mount" or "update"
|
|
109
|
+
actualDuration, // time spent rendering the committed update
|
|
110
|
+
baseDuration, // estimated time to render the entire subtree
|
|
111
|
+
startTime, // when React began rendering this update
|
|
112
|
+
commitTime // when React committed this update
|
|
113
|
+
) {
|
|
114
|
+
console.log('[PERF]', {
|
|
115
|
+
component: id,
|
|
116
|
+
phase: phase,
|
|
117
|
+
actualDuration: `${actualDuration.toFixed(2)}ms`,
|
|
118
|
+
baseDuration: `${baseDuration.toFixed(2)}ms`,
|
|
119
|
+
timestamp: new Date(commitTime).toISOString()
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Usage
|
|
124
|
+
<Profiler id="UserList" onRender={onRenderCallback}>
|
|
125
|
+
<UserList />
|
|
126
|
+
</Profiler>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Memoization Patterns
|
|
130
|
+
```javascript
|
|
131
|
+
// Optimize expensive computations
|
|
132
|
+
const ExpensiveComponent = ({ data }) => {
|
|
133
|
+
const processedData = useMemo(() => {
|
|
134
|
+
console.log('[MEMO] Processing data...');
|
|
135
|
+
return expensiveOperation(data);
|
|
136
|
+
}, [data]);
|
|
137
|
+
|
|
138
|
+
const handleClick = useCallback(() => {
|
|
139
|
+
console.log('[CALLBACK] Handler executed');
|
|
140
|
+
// Handle click
|
|
141
|
+
}, []);
|
|
142
|
+
|
|
143
|
+
return <div onClick={handleClick}>{processedData}</div>;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// Memoize entire component
|
|
147
|
+
export default React.memo(ExpensiveComponent);
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Security Best Practices
|
|
153
|
+
|
|
154
|
+
### XSS Prevention
|
|
155
|
+
```javascript
|
|
156
|
+
// Safe HTML rendering
|
|
157
|
+
import DOMPurify from 'dompurify';
|
|
158
|
+
|
|
159
|
+
function SafeHTML({ html }) {
|
|
160
|
+
const sanitizedHTML = DOMPurify.sanitize(html);
|
|
161
|
+
|
|
162
|
+
return <div dangerouslySetInnerHTML={{ __html: sanitizedHTML }} />;
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Input Validation
|
|
167
|
+
```javascript
|
|
168
|
+
// Form validation patterns
|
|
169
|
+
const validateInput = (value, rules) => {
|
|
170
|
+
const errors = [];
|
|
171
|
+
|
|
172
|
+
if (rules.required && !value) {
|
|
173
|
+
errors.push('Field is required');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (rules.email && value && !/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(value)) {
|
|
177
|
+
errors.push('Invalid email format');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (rules.minLength && value && value.length < rules.minLength) {
|
|
181
|
+
errors.push(`Minimum length is ${rules.minLength}`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return errors;
|
|
185
|
+
};
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Testing Requirements
|
|
191
|
+
|
|
192
|
+
### Jest + React Testing Library
|
|
193
|
+
```javascript
|
|
194
|
+
// Component testing
|
|
195
|
+
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
196
|
+
import '@testing-library/jest-dom';
|
|
197
|
+
import UserProfile from './UserProfile';
|
|
198
|
+
|
|
199
|
+
describe('UserProfile', () => {
|
|
200
|
+
it('renders user information', async () => {
|
|
201
|
+
render(<UserProfile userId="123" />);
|
|
202
|
+
|
|
203
|
+
await waitFor(() => {
|
|
204
|
+
expect(screen.getByText(/John Doe/i)).toBeInTheDocument();
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('handles user interaction', async () => {
|
|
209
|
+
const handleClick = jest.fn();
|
|
210
|
+
render(<UserProfile userId="123" onEdit={handleClick} />);
|
|
211
|
+
|
|
212
|
+
fireEvent.click(screen.getByRole('button', { name: /edit/i }));
|
|
213
|
+
|
|
214
|
+
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Hook Testing
|
|
220
|
+
```javascript
|
|
221
|
+
// Custom hook testing
|
|
222
|
+
import { renderHook, act } from '@testing-library/react';
|
|
223
|
+
import { useCounter } from './useCounter';
|
|
224
|
+
|
|
225
|
+
describe('useCounter', () => {
|
|
226
|
+
it('increments counter', () => {
|
|
227
|
+
const { result } = renderHook(() => useCounter(0));
|
|
228
|
+
|
|
229
|
+
act(() => {
|
|
230
|
+
result.current.increment();
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
expect(result.current.count).toBe(1);
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Framework Best Practices
|
|
241
|
+
|
|
242
|
+
### Component Structure
|
|
243
|
+
```javascript
|
|
244
|
+
// Standard component structure
|
|
245
|
+
import React, { useState, useEffect, useCallback } from 'react';
|
|
246
|
+
import PropTypes from 'prop-types';
|
|
247
|
+
|
|
248
|
+
const UserProfile = ({ userId, onUpdate }) => {
|
|
249
|
+
// State declarations
|
|
250
|
+
const [user, setUser] = useState(null);
|
|
251
|
+
const [loading, setLoading] = useState(true);
|
|
252
|
+
const [error, setError] = useState(null);
|
|
253
|
+
|
|
254
|
+
// Effects
|
|
255
|
+
useEffect(() => {
|
|
256
|
+
fetchUser(userId)
|
|
257
|
+
.then(setUser)
|
|
258
|
+
.catch(setError)
|
|
259
|
+
.finally(() => setLoading(false));
|
|
260
|
+
}, [userId]);
|
|
261
|
+
|
|
262
|
+
// Callbacks
|
|
263
|
+
const handleUpdate = useCallback(() => {
|
|
264
|
+
onUpdate(user);
|
|
265
|
+
}, [user, onUpdate]);
|
|
266
|
+
|
|
267
|
+
// Render logic
|
|
268
|
+
if (loading) return <div>Loading...</div>;
|
|
269
|
+
if (error) return <div>Error: {error.message}</div>;
|
|
270
|
+
|
|
271
|
+
return (
|
|
272
|
+
<div className="user-profile">
|
|
273
|
+
<h1>{user.name}</h1>
|
|
274
|
+
<button onClick={handleUpdate}>Update</button>
|
|
275
|
+
</div>
|
|
276
|
+
);
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
// PropTypes validation
|
|
280
|
+
UserProfile.propTypes = {
|
|
281
|
+
userId: PropTypes.string.isRequired,
|
|
282
|
+
onUpdate: PropTypes.func.isRequired
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
export default UserProfile;
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Custom Hooks
|
|
289
|
+
```javascript
|
|
290
|
+
// Reusable custom hook
|
|
291
|
+
function useFetch(url, options = {}) {
|
|
292
|
+
const [data, setData] = useState(null);
|
|
293
|
+
const [loading, setLoading] = useState(true);
|
|
294
|
+
const [error, setError] = useState(null);
|
|
295
|
+
|
|
296
|
+
useEffect(() => {
|
|
297
|
+
console.log('[HOOK] useFetch', { url, options });
|
|
298
|
+
|
|
299
|
+
const abortController = new AbortController();
|
|
300
|
+
|
|
301
|
+
fetch(url, { ...options, signal: abortController.signal })
|
|
302
|
+
.then(res => res.json())
|
|
303
|
+
.then(setData)
|
|
304
|
+
.catch(err => {
|
|
305
|
+
if (err.name !== 'AbortError') {
|
|
306
|
+
setError(err);
|
|
307
|
+
}
|
|
308
|
+
})
|
|
309
|
+
.finally(() => setLoading(false));
|
|
310
|
+
|
|
311
|
+
return () => abortController.abort();
|
|
312
|
+
}, [url, JSON.stringify(options)]);
|
|
313
|
+
|
|
314
|
+
return { data, loading, error };
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## Error Handling Patterns
|
|
321
|
+
|
|
322
|
+
### Error Boundaries
|
|
323
|
+
```javascript
|
|
324
|
+
// Error boundary component
|
|
325
|
+
class ErrorBoundary extends React.Component {
|
|
326
|
+
constructor(props) {
|
|
327
|
+
super(props);
|
|
328
|
+
this.state = { hasError: false, error: null };
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
static getDerivedStateFromError(error) {
|
|
332
|
+
return { hasError: true, error };
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
componentDidCatch(error, errorInfo) {
|
|
336
|
+
console.error('[ERROR-BOUNDARY]', {
|
|
337
|
+
error: error.message,
|
|
338
|
+
componentStack: errorInfo.componentStack,
|
|
339
|
+
timestamp: new Date().toISOString()
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
// Report to error tracking service
|
|
343
|
+
// reportError(error, errorInfo);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
render() {
|
|
347
|
+
if (this.state.hasError) {
|
|
348
|
+
return (
|
|
349
|
+
<div className="error-fallback">
|
|
350
|
+
<h1>Something went wrong</h1>
|
|
351
|
+
<details>
|
|
352
|
+
<summary>Error details</summary>
|
|
353
|
+
<pre>{this.state.error?.message}</pre>
|
|
354
|
+
</details>
|
|
355
|
+
</div>
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return this.props.children;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Usage
|
|
364
|
+
<ErrorBoundary>
|
|
365
|
+
<App />
|
|
366
|
+
</ErrorBoundary>
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Async Error Handling
|
|
370
|
+
```javascript
|
|
371
|
+
// Safe async operations
|
|
372
|
+
async function safeAsync(operation, errorHandler) {
|
|
373
|
+
try {
|
|
374
|
+
return await operation();
|
|
375
|
+
} catch (error) {
|
|
376
|
+
console.error('[ASYNC-ERROR]', {
|
|
377
|
+
error: error.message,
|
|
378
|
+
stack: error.stack,
|
|
379
|
+
timestamp: new Date().toISOString()
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
if (errorHandler) {
|
|
383
|
+
return errorHandler(error);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
throw error;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## Technology-Specific Command References
|
|
394
|
+
|
|
395
|
+
### Development Commands
|
|
396
|
+
```bash
|
|
397
|
+
# Development
|
|
398
|
+
npm start # Start dev server
|
|
399
|
+
npm run dev # Alternative dev command
|
|
400
|
+
npm run build # Production build
|
|
401
|
+
npm run preview # Preview production build
|
|
402
|
+
|
|
403
|
+
# Type Checking (if TypeScript)
|
|
404
|
+
npm run type-check # Check types
|
|
405
|
+
tsc --noEmit # TypeScript compilation check
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Testing Commands
|
|
409
|
+
```bash
|
|
410
|
+
# Testing
|
|
411
|
+
npm test # Run tests
|
|
412
|
+
npm run test:watch # Watch mode
|
|
413
|
+
npm run test:coverage # Generate coverage
|
|
414
|
+
npm run test:debug # Debug tests
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
## State Management Patterns
|
|
420
|
+
|
|
421
|
+
### Context API
|
|
422
|
+
```javascript
|
|
423
|
+
// Context setup
|
|
424
|
+
const UserContext = React.createContext(null);
|
|
425
|
+
|
|
426
|
+
export const UserProvider = ({ children }) => {
|
|
427
|
+
const [user, setUser] = useState(null);
|
|
428
|
+
|
|
429
|
+
const login = useCallback(async (credentials) => {
|
|
430
|
+
const user = await authService.login(credentials);
|
|
431
|
+
setUser(user);
|
|
432
|
+
}, []);
|
|
433
|
+
|
|
434
|
+
const logout = useCallback(() => {
|
|
435
|
+
setUser(null);
|
|
436
|
+
}, []);
|
|
437
|
+
|
|
438
|
+
const value = useMemo(
|
|
439
|
+
() => ({ user, login, logout }),
|
|
440
|
+
[user, login, logout]
|
|
441
|
+
);
|
|
442
|
+
|
|
443
|
+
return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
export const useUser = () => {
|
|
447
|
+
const context = useContext(UserContext);
|
|
448
|
+
if (!context) {
|
|
449
|
+
throw new Error('useUser must be used within UserProvider');
|
|
450
|
+
}
|
|
451
|
+
return context;
|
|
452
|
+
};
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### Redux (if applicable)
|
|
456
|
+
```javascript
|
|
457
|
+
// Redux slice
|
|
458
|
+
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
|
|
459
|
+
|
|
460
|
+
export const fetchUsers = createAsyncThunk(
|
|
461
|
+
'users/fetchUsers',
|
|
462
|
+
async () => {
|
|
463
|
+
console.log('[REDUX] Fetching users...');
|
|
464
|
+
const response = await api.getUsers();
|
|
465
|
+
return response.data;
|
|
466
|
+
}
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
const usersSlice = createSlice({
|
|
470
|
+
name: 'users',
|
|
471
|
+
initialState: { entities: [], loading: false, error: null },
|
|
472
|
+
reducers: {},
|
|
473
|
+
extraReducers: (builder) => {
|
|
474
|
+
builder
|
|
475
|
+
.addCase(fetchUsers.pending, (state) => {
|
|
476
|
+
state.loading = true;
|
|
477
|
+
})
|
|
478
|
+
.addCase(fetchUsers.fulfilled, (state, action) => {
|
|
479
|
+
state.entities = action.payload;
|
|
480
|
+
state.loading = false;
|
|
481
|
+
})
|
|
482
|
+
.addCase(fetchUsers.rejected, (state, action) => {
|
|
483
|
+
state.error = action.error.message;
|
|
484
|
+
state.loading = false;
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
export default usersSlice.reducer;
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
494
|
+
## Reference to Parent Context
|
|
495
|
+
|
|
496
|
+
This file extends the Trinity Method protocols defined in `../.claude/trinity/CLAUDE.md` and global requirements from `../CLAUDE.md`. React implementations must comply with:
|
|
497
|
+
|
|
498
|
+
- Trinity Method investigation requirements ([../.claude/trinity/CLAUDE.md](../.claude/trinity/CLAUDE.md))
|
|
499
|
+
- Global performance baselines ([../.claude/trinity/knowledge-base/ARCHITECTURE.md](../.claude/trinity/knowledge-base/ARCHITECTURE.md#performance-baseline))
|
|
500
|
+
- Quality gate standards (BAS 6-phase) ([../.claude/trinity/CLAUDE.md](../.claude/trinity/CLAUDE.md#quality-standards))
|
|
501
|
+
- Crisis management protocols ([../.claude/trinity/CLAUDE.md](../.claude/trinity/CLAUDE.md#crisis-management))
|
|
502
|
+
|
|
503
|
+
All React code must implement the debugging frameworks, error handling patterns, and performance monitoring specified in this document.
|
|
504
|
+
|
|
505
|
+
---
|
|
506
|
+
|
|
507
|
+
**Technology Context**: React Implementation
|
|
508
|
+
**Parent References**:
|
|
509
|
+
- `../CLAUDE.md` - Global project requirements
|
|
510
|
+
- `../.claude/trinity/CLAUDE.md` - Trinity Method enforcement
|
|
511
|
+
|
|
512
|
+
**Last Updated**: {{CURRENT_DATE}}
|
|
513
|
+
**Trinity Version**: {{TRINITY_VERSION}}
|