@su-record/vibe 2.7.10 → 2.7.12
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/.env.example +37 -37
- package/CLAUDE.md +126 -222
- package/LICENSE +21 -21
- package/README.md +580 -580
- package/agents/architect-low.md +41 -41
- package/agents/architect-medium.md +59 -59
- package/agents/architect.md +80 -80
- package/agents/build-error-resolver.md +115 -115
- package/agents/compounder.md +261 -261
- package/agents/diagrammer.md +178 -178
- package/agents/docs/api-documenter.md +99 -99
- package/agents/docs/changelog-writer.md +93 -93
- package/agents/e2e-tester.md +266 -266
- package/agents/explorer-low.md +42 -42
- package/agents/explorer-medium.md +59 -59
- package/agents/explorer.md +48 -48
- package/agents/implementer-low.md +43 -43
- package/agents/implementer-medium.md +52 -52
- package/agents/implementer.md +54 -54
- package/agents/junior-mentor.md +141 -141
- package/agents/planning/requirements-analyst.md +84 -84
- package/agents/planning/ux-advisor.md +83 -83
- package/agents/qa/acceptance-tester.md +86 -86
- package/agents/qa/edge-case-finder.md +93 -93
- package/agents/refactor-cleaner.md +143 -143
- package/agents/research/best-practices-agent.md +199 -199
- package/agents/research/codebase-patterns-agent.md +157 -157
- package/agents/research/framework-docs-agent.md +188 -188
- package/agents/research/security-advisory-agent.md +213 -213
- package/agents/review/architecture-reviewer.md +107 -107
- package/agents/review/complexity-reviewer.md +116 -116
- package/agents/review/data-integrity-reviewer.md +88 -88
- package/agents/review/git-history-reviewer.md +103 -103
- package/agents/review/performance-reviewer.md +86 -86
- package/agents/review/python-reviewer.md +150 -150
- package/agents/review/rails-reviewer.md +139 -139
- package/agents/review/react-reviewer.md +144 -144
- package/agents/review/security-reviewer.md +80 -80
- package/agents/review/simplicity-reviewer.md +140 -140
- package/agents/review/test-coverage-reviewer.md +116 -116
- package/agents/review/typescript-reviewer.md +127 -127
- package/agents/searcher.md +54 -54
- package/agents/simplifier.md +120 -120
- package/agents/tester.md +49 -49
- package/agents/ui/ui-a11y-auditor.md +93 -93
- package/agents/ui/ui-antipattern-detector.md +94 -94
- package/agents/ui/ui-dataviz-advisor.md +69 -69
- package/agents/ui/ui-design-system-gen.md +57 -57
- package/agents/ui/ui-industry-analyzer.md +49 -49
- package/agents/ui/ui-layout-architect.md +65 -65
- package/agents/ui/ui-stack-implementer.md +68 -68
- package/agents/ui/ux-compliance-reviewer.md +81 -81
- package/agents/ui-previewer.md +260 -260
- package/commands/vibe.run.md +83 -0
- package/commands/vibe.spec.review.md +558 -558
- package/commands/vibe.utils.md +413 -413
- package/commands/vibe.voice.md +79 -79
- package/dist/cli/auth.d.ts +1 -1
- package/dist/cli/auth.d.ts.map +1 -1
- package/dist/cli/auth.js +15 -7
- package/dist/cli/auth.js.map +1 -1
- package/dist/cli/collaborator.js +52 -52
- package/dist/cli/commands/evolution.js +12 -12
- package/dist/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +1 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/info.d.ts.map +1 -1
- package/dist/cli/commands/info.js +62 -56
- package/dist/cli/commands/info.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +9 -6
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/remove.js +14 -14
- package/dist/cli/commands/sentinel.js +27 -27
- package/dist/cli/commands/skills.d.ts +13 -0
- package/dist/cli/commands/skills.d.ts.map +1 -0
- package/dist/cli/commands/skills.js +83 -0
- package/dist/cli/commands/skills.js.map +1 -0
- package/dist/cli/commands/slack.js +10 -10
- package/dist/cli/commands/telegram.js +12 -12
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +3 -0
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/detect.js +32 -32
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +64 -47
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/llm/claude-commands.js +16 -16
- package/dist/cli/llm/config.js +18 -18
- package/dist/cli/llm/gemini-commands.js +47 -47
- package/dist/cli/llm/gpt-commands.js +19 -19
- package/dist/cli/llm/help.js +21 -21
- package/dist/cli/postinstall/constants.d.ts +8 -0
- package/dist/cli/postinstall/constants.d.ts.map +1 -1
- package/dist/cli/postinstall/constants.js +33 -0
- package/dist/cli/postinstall/constants.js.map +1 -1
- package/dist/cli/postinstall/cursor-agents.js +32 -32
- package/dist/cli/postinstall/cursor-rules.js +83 -83
- package/dist/cli/postinstall/cursor-skills.js +743 -743
- package/dist/cli/postinstall/index.d.ts +1 -1
- package/dist/cli/postinstall/index.d.ts.map +1 -1
- package/dist/cli/postinstall/index.js +1 -1
- package/dist/cli/postinstall/index.js.map +1 -1
- package/dist/cli/setup/ProjectSetup.d.ts.map +1 -1
- package/dist/cli/setup/ProjectSetup.js +5 -0
- package/dist/cli/setup/ProjectSetup.js.map +1 -1
- package/dist/cli/setup/Provisioner.js +42 -42
- package/dist/cli/types.d.ts +1 -0
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/infra/lib/DeepInit.js +24 -24
- package/dist/infra/lib/IterationTracker.js +11 -11
- package/dist/infra/lib/PythonParser.js +108 -108
- package/dist/infra/lib/ReviewRace.js +96 -96
- package/dist/infra/lib/SkillFrontmatter.js +28 -28
- package/dist/infra/lib/SkillQualityGate.js +9 -9
- package/dist/infra/lib/SkillRepository.js +159 -159
- package/dist/infra/lib/UltraQA.js +99 -99
- package/dist/infra/lib/autonomy/AuditStore.js +41 -41
- package/dist/infra/lib/autonomy/ConfirmationStore.js +30 -30
- package/dist/infra/lib/autonomy/EventOutbox.js +38 -38
- package/dist/infra/lib/autonomy/PolicyEngine.js +18 -18
- package/dist/infra/lib/autonomy/SecuritySentinel.js +1 -1
- package/dist/infra/lib/autonomy/SuggestionStore.js +33 -33
- package/dist/infra/lib/embedding/VectorStore.js +22 -22
- package/dist/infra/lib/evolution/AgentAnalyzer.js +10 -10
- package/dist/infra/lib/evolution/DescriptionOptimizer.d.ts +79 -0
- package/dist/infra/lib/evolution/DescriptionOptimizer.d.ts.map +1 -0
- package/dist/infra/lib/evolution/DescriptionOptimizer.js +259 -0
- package/dist/infra/lib/evolution/DescriptionOptimizer.js.map +1 -0
- package/dist/infra/lib/evolution/GenerationRegistry.js +36 -36
- package/dist/infra/lib/evolution/InsightStore.js +90 -90
- package/dist/infra/lib/evolution/RollbackManager.js +5 -5
- package/dist/infra/lib/evolution/SkillBenchmark.d.ts +81 -0
- package/dist/infra/lib/evolution/SkillBenchmark.d.ts.map +1 -0
- package/dist/infra/lib/evolution/SkillBenchmark.js +233 -0
- package/dist/infra/lib/evolution/SkillBenchmark.js.map +1 -0
- package/dist/infra/lib/evolution/SkillClassifier.d.ts +35 -0
- package/dist/infra/lib/evolution/SkillClassifier.d.ts.map +1 -0
- package/dist/infra/lib/evolution/SkillClassifier.js +167 -0
- package/dist/infra/lib/evolution/SkillClassifier.js.map +1 -0
- package/dist/infra/lib/evolution/SkillEvalRunner.d.ts +102 -0
- package/dist/infra/lib/evolution/SkillEvalRunner.d.ts.map +1 -0
- package/dist/infra/lib/evolution/SkillEvalRunner.js +256 -0
- package/dist/infra/lib/evolution/SkillEvalRunner.js.map +1 -0
- package/dist/infra/lib/evolution/SkillGapDetector.js +10 -10
- package/dist/infra/lib/evolution/UsageTracker.js +28 -28
- package/dist/infra/lib/evolution/__tests__/eval.test.d.ts +2 -0
- package/dist/infra/lib/evolution/__tests__/eval.test.d.ts.map +1 -0
- package/dist/infra/lib/evolution/__tests__/eval.test.js +539 -0
- package/dist/infra/lib/evolution/__tests__/eval.test.js.map +1 -0
- package/dist/infra/lib/evolution/index.d.ts +8 -0
- package/dist/infra/lib/evolution/index.d.ts.map +1 -1
- package/dist/infra/lib/evolution/index.js +5 -0
- package/dist/infra/lib/evolution/index.js.map +1 -1
- package/dist/infra/lib/gemini/constants.js +14 -14
- package/dist/infra/lib/gemini/orchestration.js +5 -5
- package/dist/infra/lib/gpt/oauth.js +44 -44
- package/dist/infra/lib/gpt/orchestration.js +4 -4
- package/dist/infra/lib/memory/KnowledgeGraph.js +4 -4
- package/dist/infra/lib/memory/MemorySearch.js +57 -57
- package/dist/infra/lib/memory/MemoryStorage.js +181 -181
- package/dist/infra/lib/memory/ObservationStore.js +28 -28
- package/dist/infra/lib/memory/ReflectionStore.js +30 -30
- package/dist/infra/lib/memory/SessionRAGRetriever.js +7 -7
- package/dist/infra/lib/memory/SessionRAGStore.js +225 -225
- package/dist/infra/lib/memory/SessionSummarizer.js +9 -9
- package/dist/infra/orchestrator/AgentManager.js +12 -12
- package/dist/infra/orchestrator/AgentRegistry.js +65 -65
- package/dist/infra/orchestrator/MultiLlmResearch.js +8 -8
- package/dist/infra/orchestrator/SwarmOrchestrator.test.js +16 -16
- package/dist/infra/orchestrator/parallelResearch.js +24 -24
- package/dist/tools/convention/analyzeComplexity.test.js +115 -115
- package/dist/tools/convention/validateCodeQuality.test.js +104 -104
- package/dist/tools/memory/createMemoryTimeline.js +10 -10
- package/dist/tools/memory/getMemoryGraph.js +12 -12
- package/dist/tools/memory/getSessionContext.js +9 -9
- package/dist/tools/memory/linkMemories.js +14 -14
- package/dist/tools/memory/listMemories.js +4 -4
- package/dist/tools/memory/recallMemory.js +4 -4
- package/dist/tools/memory/saveMemory.js +4 -4
- package/dist/tools/memory/searchMemoriesAdvanced.js +23 -23
- package/dist/tools/semantic/analyzeDependencyGraph.js +12 -12
- package/dist/tools/semantic/astGrep.test.js +6 -6
- package/dist/tools/spec/prdParser.test.js +171 -171
- package/dist/tools/spec/specGenerator.js +169 -169
- package/dist/tools/spec/traceabilityMatrix.js +64 -64
- package/dist/tools/spec/traceabilityMatrix.test.js +28 -28
- package/hooks/gemini-hooks.json +73 -73
- package/hooks/hooks.json +137 -137
- package/hooks/scripts/code-check.js +70 -70
- package/hooks/scripts/context-save.js +212 -212
- package/hooks/scripts/hud-status.js +291 -291
- package/hooks/scripts/keyword-detector.js +214 -214
- package/hooks/scripts/llm-orchestrate.js +646 -646
- package/hooks/scripts/post-edit.js +32 -32
- package/hooks/scripts/pre-tool-guard.js +125 -125
- package/hooks/scripts/prompt-dispatcher.js +185 -185
- package/hooks/scripts/sentinel-guard.js +104 -104
- package/hooks/scripts/session-start.js +106 -106
- package/hooks/scripts/stop-notify.js +209 -209
- package/hooks/scripts/utils.js +100 -100
- package/languages/csharp-unity.md +515 -515
- package/languages/gdscript-godot.md +470 -470
- package/languages/ruby-rails.md +489 -489
- package/languages/typescript-angular.md +433 -433
- package/languages/typescript-astro.md +416 -416
- package/languages/typescript-electron.md +406 -406
- package/languages/typescript-nestjs.md +524 -524
- package/languages/typescript-svelte.md +407 -407
- package/languages/typescript-tauri.md +365 -365
- package/package.json +121 -121
- package/skills/agents-md/SKILL.md +120 -120
- package/skills/arch-guard/SKILL.md +180 -0
- package/skills/brand-assets/SKILL.md +146 -146
- package/skills/capability-loop/SKILL.md +167 -0
- package/skills/characterization-test/SKILL.md +206 -206
- package/skills/commerce-patterns/SKILL.md +59 -59
- package/skills/commit-push-pr/SKILL.md +75 -75
- package/skills/context7-usage/SKILL.md +105 -105
- package/skills/core-capabilities/SKILL.md +48 -48
- package/skills/e2e-commerce/SKILL.md +57 -57
- package/skills/exec-plan/SKILL.md +147 -0
- package/skills/frontend-design/SKILL.md +73 -73
- package/skills/git-worktree/SKILL.md +72 -72
- package/skills/handoff/SKILL.md +109 -109
- package/skills/parallel-research/SKILL.md +87 -87
- package/skills/priority-todos/SKILL.md +63 -63
- package/skills/seo-checklist/SKILL.md +57 -57
- package/skills/techdebt/SKILL.md +122 -122
- package/skills/tool-fallback/SKILL.md +103 -103
- package/skills/typescript-advanced-types/SKILL.md +65 -65
- package/skills/ui-ux-pro-max/SKILL.md +206 -206
- package/skills/vercel-react-best-practices/SKILL.md +59 -59
- package/skills/video-production/SKILL.md +51 -51
- package/vibe/config.json +29 -29
- package/vibe/constitution.md +227 -227
- package/vibe/rules/principles/communication-guide.md +98 -98
- package/vibe/rules/principles/development-philosophy.md +52 -52
- package/vibe/rules/principles/quick-start.md +102 -102
- package/vibe/rules/quality/bdd-contract-testing.md +393 -393
- package/vibe/rules/quality/checklist.md +276 -276
- package/vibe/rules/quality/performance.md +236 -236
- package/vibe/rules/quality/testing-strategy.md +440 -440
- package/vibe/rules/standards/anti-patterns.md +541 -541
- package/vibe/rules/standards/code-structure.md +291 -291
- package/vibe/rules/standards/complexity-metrics.md +313 -313
- package/vibe/rules/standards/git-workflow.md +237 -237
- package/vibe/rules/standards/naming-conventions.md +198 -198
- package/vibe/rules/standards/security.md +305 -305
- package/vibe/rules/writing/document-style.md +74 -74
- package/vibe/setup.sh +31 -31
- package/vibe/templates/constitution-template.md +252 -252
- package/vibe/templates/contract-backend-template.md +526 -526
- package/vibe/templates/contract-frontend-template.md +599 -599
- package/vibe/templates/feature-template.md +96 -96
- package/vibe/templates/spec-template.md +221 -221
- package/vibe/ui-ux-data/charts.csv +26 -26
- package/vibe/ui-ux-data/colors.csv +97 -97
- package/vibe/ui-ux-data/icons.csv +101 -101
- package/vibe/ui-ux-data/landing.csv +31 -31
- package/vibe/ui-ux-data/products.csv +96 -96
- package/vibe/ui-ux-data/react-performance.csv +45 -45
- package/vibe/ui-ux-data/stacks/astro.csv +54 -54
- package/vibe/ui-ux-data/stacks/flutter.csv +53 -53
- package/vibe/ui-ux-data/stacks/html-tailwind.csv +56 -56
- package/vibe/ui-ux-data/stacks/jetpack-compose.csv +53 -53
- package/vibe/ui-ux-data/stacks/nextjs.csv +53 -53
- package/vibe/ui-ux-data/stacks/nuxt-ui.csv +51 -51
- package/vibe/ui-ux-data/stacks/nuxtjs.csv +59 -59
- package/vibe/ui-ux-data/stacks/react-native.csv +52 -52
- package/vibe/ui-ux-data/stacks/react.csv +54 -54
- package/vibe/ui-ux-data/stacks/shadcn.csv +61 -61
- package/vibe/ui-ux-data/stacks/svelte.csv +54 -54
- package/vibe/ui-ux-data/stacks/swiftui.csv +51 -51
- package/vibe/ui-ux-data/stacks/vue.csv +50 -50
- package/vibe/ui-ux-data/styles.csv +68 -68
- package/vibe/ui-ux-data/typography.csv +57 -57
- package/vibe/ui-ux-data/ui-reasoning.csv +101 -101
- package/vibe/ui-ux-data/ux-guidelines.csv +99 -99
- package/vibe/ui-ux-data/version.json +31 -31
- package/vibe/ui-ux-data/web-interface.csv +31 -31
|
@@ -1,541 +1,541 @@
|
|
|
1
|
-
# Automatic Anti-Pattern Avoidance
|
|
2
|
-
|
|
3
|
-
## TypeScript Anti-Patterns
|
|
4
|
-
|
|
5
|
-
### 1. Using any Type
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
// ❌ Using any
|
|
9
|
-
function processData(data: any) {
|
|
10
|
-
return data.value; // Loss of type safety
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// ✅ unknown + type guard
|
|
14
|
-
function processData(data: unknown) {
|
|
15
|
-
if (isValidData(data)) {
|
|
16
|
-
return data.value; // Type safe
|
|
17
|
-
}
|
|
18
|
-
throw new Error('Invalid data');
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function isValidData(data: unknown): data is { value: string } {
|
|
22
|
-
return typeof data === 'object' && data !== null && 'value' in data;
|
|
23
|
-
}
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
### 2. Forced Type Casting with as any
|
|
27
|
-
|
|
28
|
-
```typescript
|
|
29
|
-
// ❌ Bypassing types with as any
|
|
30
|
-
const user = response as any;
|
|
31
|
-
user.name; // Runtime error risk
|
|
32
|
-
|
|
33
|
-
// ✅ Proper type definition
|
|
34
|
-
interface User {
|
|
35
|
-
name: string;
|
|
36
|
-
email: string;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const user = response as User;
|
|
40
|
-
user.name; // Type safe
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### 3. Overusing @ts-ignore
|
|
44
|
-
|
|
45
|
-
```typescript
|
|
46
|
-
// ❌ Ignoring errors with @ts-ignore
|
|
47
|
-
// @ts-ignore
|
|
48
|
-
const result = problematicCode();
|
|
49
|
-
|
|
50
|
-
// ✅ Fix the type issue at its root
|
|
51
|
-
interface Expected {
|
|
52
|
-
id: string;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const result: Expected = {
|
|
56
|
-
id: String(problematicCode()),
|
|
57
|
-
};
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## React Anti-Patterns
|
|
61
|
-
|
|
62
|
-
### 1. Using dangerouslySetInnerHTML
|
|
63
|
-
|
|
64
|
-
```typescript
|
|
65
|
-
// ❌ XSS vulnerability
|
|
66
|
-
function Component({ html }: { html: string }) {
|
|
67
|
-
return <div dangerouslySetInnerHTML={{ __html: html }} />;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// ✅ Safe rendering
|
|
71
|
-
import DOMPurify from 'dompurify';
|
|
72
|
-
|
|
73
|
-
function Component({ html }: { html: string }) {
|
|
74
|
-
const sanitized = DOMPurify.sanitize(html);
|
|
75
|
-
return <div dangerouslySetInnerHTML={{ __html: sanitized }} />;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// ✅ Better approach: Use markdown library
|
|
79
|
-
import ReactMarkdown from 'react-markdown';
|
|
80
|
-
|
|
81
|
-
function Component({ markdown }: { markdown: string }) {
|
|
82
|
-
return <ReactMarkdown>{markdown}</ReactMarkdown>;
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### 2. Props Drilling (More than 3 levels)
|
|
87
|
-
|
|
88
|
-
```typescript
|
|
89
|
-
// ❌ Props drilling
|
|
90
|
-
function App() {
|
|
91
|
-
const [user, setUser] = useState<User>();
|
|
92
|
-
return <Parent user={user} />;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function Parent({ user }: { user: User }) {
|
|
96
|
-
return <Child user={user} />;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function Child({ user }: { user: User }) {
|
|
100
|
-
return <GrandChild user={user} />;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function GrandChild({ user }: { user: User }) {
|
|
104
|
-
return <div>{user.name}</div>;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// ✅ Use Context API
|
|
108
|
-
const UserContext = createContext<User | undefined>(undefined);
|
|
109
|
-
|
|
110
|
-
function App() {
|
|
111
|
-
const [user, setUser] = useState<User>();
|
|
112
|
-
return (
|
|
113
|
-
<UserContext.Provider value={user}>
|
|
114
|
-
<Parent />
|
|
115
|
-
</UserContext.Provider>
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function GrandChild() {
|
|
120
|
-
const user = useContext(UserContext);
|
|
121
|
-
return <div>{user?.name}</div>;
|
|
122
|
-
}
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
### 3. Missing useEffect Dependency Array
|
|
126
|
-
|
|
127
|
-
```typescript
|
|
128
|
-
// ❌ Missing dependency
|
|
129
|
-
function Component({ userId }: { userId: string }) {
|
|
130
|
-
const [user, setUser] = useState<User>();
|
|
131
|
-
|
|
132
|
-
useEffect(() => {
|
|
133
|
-
fetchUser(userId).then(setUser);
|
|
134
|
-
}, []); // Missing userId dependency!
|
|
135
|
-
|
|
136
|
-
return <div>{user?.name}</div>;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// ✅ Specify all dependencies
|
|
140
|
-
function Component({ userId }: { userId: string }) {
|
|
141
|
-
const [user, setUser] = useState<User>();
|
|
142
|
-
|
|
143
|
-
useEffect(() => {
|
|
144
|
-
fetchUser(userId).then(setUser);
|
|
145
|
-
}, [userId]); // Dependency specified
|
|
146
|
-
|
|
147
|
-
return <div>{user?.name}</div>;
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
## JavaScript Anti-Patterns
|
|
152
|
-
|
|
153
|
-
### 1. Using var
|
|
154
|
-
|
|
155
|
-
```typescript
|
|
156
|
-
// ❌ Using var
|
|
157
|
-
var count = 0;
|
|
158
|
-
if (true) {
|
|
159
|
-
var count = 1; // Same variable!
|
|
160
|
-
}
|
|
161
|
-
console.log(count); // 1
|
|
162
|
-
|
|
163
|
-
// ✅ Use const/let
|
|
164
|
-
let count = 0;
|
|
165
|
-
if (true) {
|
|
166
|
-
let count = 1; // Block scope
|
|
167
|
-
}
|
|
168
|
-
console.log(count); // 0
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### 2. Using == (Loose Comparison)
|
|
172
|
-
|
|
173
|
-
```typescript
|
|
174
|
-
// ❌ Using ==
|
|
175
|
-
if (value == null) { } // Also matches undefined
|
|
176
|
-
if ('5' == 5) { } // true (type coercion)
|
|
177
|
-
|
|
178
|
-
// ✅ Use ===
|
|
179
|
-
if (value === null) { }
|
|
180
|
-
if (value === undefined) { }
|
|
181
|
-
if ('5' === 5) { } // false
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
### 3. Using eval()
|
|
185
|
-
|
|
186
|
-
```typescript
|
|
187
|
-
// ❌ Using eval() (security risk)
|
|
188
|
-
const code = userInput;
|
|
189
|
-
eval(code); // Can execute arbitrary code
|
|
190
|
-
|
|
191
|
-
// ✅ Alternative implementation
|
|
192
|
-
const allowedOperations = {
|
|
193
|
-
add: (a: number, b: number) => a + b,
|
|
194
|
-
subtract: (a: number, b: number) => a - b,
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
const operation = allowedOperations[userInput];
|
|
198
|
-
if (operation) {
|
|
199
|
-
result = operation(a, b);
|
|
200
|
-
}
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
## CSS Anti-Patterns
|
|
204
|
-
|
|
205
|
-
### 1. Overusing !important
|
|
206
|
-
|
|
207
|
-
```css
|
|
208
|
-
/* ❌ Overusing !important */
|
|
209
|
-
.button {
|
|
210
|
-
color: blue !important;
|
|
211
|
-
background: red !important;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/* ✅ Use specific selectors */
|
|
215
|
-
.navigation .button.primary {
|
|
216
|
-
color: blue;
|
|
217
|
-
background: red;
|
|
218
|
-
}
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
### 2. Overusing Inline Styles
|
|
222
|
-
|
|
223
|
-
```typescript
|
|
224
|
-
// ❌ Inline styles
|
|
225
|
-
function Button() {
|
|
226
|
-
return (
|
|
227
|
-
<button
|
|
228
|
-
style={{
|
|
229
|
-
backgroundColor: 'blue',
|
|
230
|
-
color: 'white',
|
|
231
|
-
padding: '10px',
|
|
232
|
-
borderRadius: '5px',
|
|
233
|
-
}}
|
|
234
|
-
>
|
|
235
|
-
Click me
|
|
236
|
-
</button>
|
|
237
|
-
);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// ✅ Use CSS classes
|
|
241
|
-
function Button() {
|
|
242
|
-
return <button className="btn-primary">Click me</button>;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// styles.css
|
|
246
|
-
.btn-primary {
|
|
247
|
-
background-color: blue;
|
|
248
|
-
color: white;
|
|
249
|
-
padding: 10px;
|
|
250
|
-
border-radius: 5px;
|
|
251
|
-
}
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
## Performance Anti-Patterns
|
|
255
|
-
|
|
256
|
-
### 1. Unnecessary Re-renders
|
|
257
|
-
|
|
258
|
-
```typescript
|
|
259
|
-
// ❌ Creating new objects/functions every render
|
|
260
|
-
function Parent() {
|
|
261
|
-
return <Child config={{ theme: 'dark' }} onClick={() => {}} />;
|
|
262
|
-
// New object/function created every render → Child re-renders
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// ✅ Use useMemo/useCallback
|
|
266
|
-
function Parent() {
|
|
267
|
-
const config = useMemo(() => ({ theme: 'dark' }), []);
|
|
268
|
-
const handleClick = useCallback(() => {}, []);
|
|
269
|
-
|
|
270
|
-
return <Child config={config} onClick={handleClick} />;
|
|
271
|
-
}
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
### 2. Synchronous Heavy Computations
|
|
275
|
-
|
|
276
|
-
```typescript
|
|
277
|
-
// ❌ Blocking main thread
|
|
278
|
-
function Component({ data }: { data: number[] }) {
|
|
279
|
-
const result = data
|
|
280
|
-
.map(heavyComputation)
|
|
281
|
-
.filter(x => x > 0)
|
|
282
|
-
.reduce((a, b) => a + b);
|
|
283
|
-
|
|
284
|
-
return <div>{result}</div>;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// ✅ Memoization with useMemo
|
|
288
|
-
function Component({ data }: { data: number[] }) {
|
|
289
|
-
const result = useMemo(
|
|
290
|
-
() =>
|
|
291
|
-
data
|
|
292
|
-
.map(heavyComputation)
|
|
293
|
-
.filter(x => x > 0)
|
|
294
|
-
.reduce((a, b) => a + b),
|
|
295
|
-
[data]
|
|
296
|
-
);
|
|
297
|
-
|
|
298
|
-
return <div>{result}</div>;
|
|
299
|
-
}
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
## Security Anti-Patterns
|
|
303
|
-
|
|
304
|
-
### 1. Hardcoding Sensitive Information
|
|
305
|
-
|
|
306
|
-
```typescript
|
|
307
|
-
// ❌ Hardcoded API key
|
|
308
|
-
const API_KEY = 'sk-1234567890abcdef';
|
|
309
|
-
|
|
310
|
-
// ✅ Use environment variables
|
|
311
|
-
const API_KEY = process.env.NEXT_PUBLIC_API_KEY;
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
### 2. SQL Injection Vulnerability
|
|
315
|
-
|
|
316
|
-
```typescript
|
|
317
|
-
// ❌ Direct string concatenation
|
|
318
|
-
const query = `SELECT * FROM users WHERE id = ${userId}`;
|
|
319
|
-
|
|
320
|
-
// ✅ Parameterized query
|
|
321
|
-
const query = 'SELECT * FROM users WHERE id = ?';
|
|
322
|
-
db.execute(query, [userId]);
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
## Immutability Anti-Patterns
|
|
326
|
-
|
|
327
|
-
### 1. Direct State Mutation
|
|
328
|
-
|
|
329
|
-
```typescript
|
|
330
|
-
// ❌ Directly mutating state
|
|
331
|
-
const [user, setUser] = useState({ name: 'John', age: 30 });
|
|
332
|
-
|
|
333
|
-
function updateAge() {
|
|
334
|
-
user.age = 31; // Direct mutation!
|
|
335
|
-
setUser(user); // React won't detect the change
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// ✅ Use spread operator for immutable update
|
|
339
|
-
function updateAge() {
|
|
340
|
-
setUser({ ...user, age: 31 }); // New object created
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
// ✅ Or use functional update
|
|
344
|
-
function updateAge() {
|
|
345
|
-
setUser(prev => ({ ...prev, age: prev.age + 1 }));
|
|
346
|
-
}
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
### 2. Array Mutation Methods
|
|
350
|
-
|
|
351
|
-
```typescript
|
|
352
|
-
// ❌ Mutating array methods
|
|
353
|
-
const [items, setItems] = useState(['a', 'b', 'c']);
|
|
354
|
-
|
|
355
|
-
function addItem(item: string) {
|
|
356
|
-
items.push(item); // Mutates original array!
|
|
357
|
-
setItems(items);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
function removeItem(index: number) {
|
|
361
|
-
items.splice(index, 1); // Mutates original array!
|
|
362
|
-
setItems(items);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// ✅ Immutable array operations
|
|
366
|
-
function addItem(item: string) {
|
|
367
|
-
setItems([...items, item]); // Spread creates new array
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
function removeItem(index: number) {
|
|
371
|
-
setItems(items.filter((_, i) => i !== index)); // filter returns new array
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
function updateItem(index: number, newValue: string) {
|
|
375
|
-
setItems(items.map((item, i) => i === index ? newValue : item));
|
|
376
|
-
}
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
### 3. Nested Object Mutation
|
|
380
|
-
|
|
381
|
-
```typescript
|
|
382
|
-
// ❌ Deeply nested mutation
|
|
383
|
-
const [state, setState] = useState({
|
|
384
|
-
user: {
|
|
385
|
-
profile: {
|
|
386
|
-
name: 'John',
|
|
387
|
-
settings: { theme: 'dark' }
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
function updateTheme(theme: string) {
|
|
393
|
-
state.user.profile.settings.theme = theme; // Deep mutation!
|
|
394
|
-
setState(state);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// ✅ Immutable deep update
|
|
398
|
-
function updateTheme(theme: string) {
|
|
399
|
-
setState({
|
|
400
|
-
...state,
|
|
401
|
-
user: {
|
|
402
|
-
...state.user,
|
|
403
|
-
profile: {
|
|
404
|
-
...state.user.profile,
|
|
405
|
-
settings: {
|
|
406
|
-
...state.user.profile.settings,
|
|
407
|
-
theme
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
// ✅ Better: Use immer for complex updates
|
|
415
|
-
import { produce } from 'immer';
|
|
416
|
-
|
|
417
|
-
function updateTheme(theme: string) {
|
|
418
|
-
setState(produce(draft => {
|
|
419
|
-
draft.user.profile.settings.theme = theme; // Safe with immer
|
|
420
|
-
}));
|
|
421
|
-
}
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
### 4. Object.assign Misuse
|
|
425
|
-
|
|
426
|
-
```typescript
|
|
427
|
-
// ❌ Object.assign mutating first argument
|
|
428
|
-
const original = { a: 1, b: 2 };
|
|
429
|
-
const updated = Object.assign(original, { b: 3 }); // Mutates original!
|
|
430
|
-
|
|
431
|
-
// ✅ Use empty object as first argument
|
|
432
|
-
const updated = Object.assign({}, original, { b: 3 });
|
|
433
|
-
|
|
434
|
-
// ✅ Or use spread (preferred)
|
|
435
|
-
const updated = { ...original, b: 3 };
|
|
436
|
-
```
|
|
437
|
-
|
|
438
|
-
### 5. Reducer State Mutation
|
|
439
|
-
|
|
440
|
-
```typescript
|
|
441
|
-
// ❌ Mutating state in reducer
|
|
442
|
-
function reducer(state: State, action: Action) {
|
|
443
|
-
switch (action.type) {
|
|
444
|
-
case 'ADD_ITEM':
|
|
445
|
-
state.items.push(action.payload); // Mutation!
|
|
446
|
-
return state;
|
|
447
|
-
default:
|
|
448
|
-
return state;
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
// ✅ Return new state
|
|
453
|
-
function reducer(state: State, action: Action) {
|
|
454
|
-
switch (action.type) {
|
|
455
|
-
case 'ADD_ITEM':
|
|
456
|
-
return {
|
|
457
|
-
...state,
|
|
458
|
-
items: [...state.items, action.payload]
|
|
459
|
-
};
|
|
460
|
-
default:
|
|
461
|
-
return state;
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
```
|
|
465
|
-
|
|
466
|
-
### 6. Mutating Function Parameters
|
|
467
|
-
|
|
468
|
-
```typescript
|
|
469
|
-
// ❌ Mutating input parameter
|
|
470
|
-
function addTimestamp(data: Record<string, unknown>) {
|
|
471
|
-
data.timestamp = Date.now(); // Mutates caller's object!
|
|
472
|
-
return data;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
// ✅ Create new object
|
|
476
|
-
function addTimestamp(data: Record<string, unknown>) {
|
|
477
|
-
return {
|
|
478
|
-
...data,
|
|
479
|
-
timestamp: Date.now()
|
|
480
|
-
};
|
|
481
|
-
}
|
|
482
|
-
```
|
|
483
|
-
|
|
484
|
-
### Immutable Methods Reference
|
|
485
|
-
|
|
486
|
-
| Mutating (Avoid) | Immutable (Use) |
|
|
487
|
-
|------------------|-----------------|
|
|
488
|
-
| `push()` | `[...arr, item]` |
|
|
489
|
-
| `pop()` | `arr.slice(0, -1)` |
|
|
490
|
-
| `shift()` | `arr.slice(1)` |
|
|
491
|
-
| `unshift()` | `[item, ...arr]` |
|
|
492
|
-
| `splice()` | `filter()` / `slice()` + spread |
|
|
493
|
-
| `sort()` | `[...arr].sort()` |
|
|
494
|
-
| `reverse()` | `[...arr].reverse()` |
|
|
495
|
-
| `obj.prop = x` | `{ ...obj, prop: x }` |
|
|
496
|
-
|
|
497
|
-
## Error Handling Anti-Patterns
|
|
498
|
-
|
|
499
|
-
### 1. Empty catch Block
|
|
500
|
-
|
|
501
|
-
```typescript
|
|
502
|
-
// ❌ Ignoring errors
|
|
503
|
-
try {
|
|
504
|
-
riskyOperation();
|
|
505
|
-
} catch (e) {
|
|
506
|
-
// Does nothing
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
// ✅ Proper error handling
|
|
510
|
-
try {
|
|
511
|
-
riskyOperation();
|
|
512
|
-
} catch (error) {
|
|
513
|
-
console.error('Operation failed:', error);
|
|
514
|
-
showErrorNotification(error);
|
|
515
|
-
trackError(error);
|
|
516
|
-
}
|
|
517
|
-
```
|
|
518
|
-
|
|
519
|
-
### 2. Handling Without Error Type Check
|
|
520
|
-
|
|
521
|
-
```typescript
|
|
522
|
-
// ❌ Treating all errors the same
|
|
523
|
-
try {
|
|
524
|
-
await fetchData();
|
|
525
|
-
} catch (error) {
|
|
526
|
-
showError('Failed'); // Not specific
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
// ✅ Handle by error type
|
|
530
|
-
try {
|
|
531
|
-
await fetchData();
|
|
532
|
-
} catch (error) {
|
|
533
|
-
if (error instanceof NetworkError) {
|
|
534
|
-
showError('Please check your network connection');
|
|
535
|
-
} else if (error instanceof AuthError) {
|
|
536
|
-
redirectToLogin();
|
|
537
|
-
} else {
|
|
538
|
-
showError('An unknown error occurred');
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
```
|
|
1
|
+
# Automatic Anti-Pattern Avoidance
|
|
2
|
+
|
|
3
|
+
## TypeScript Anti-Patterns
|
|
4
|
+
|
|
5
|
+
### 1. Using any Type
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// ❌ Using any
|
|
9
|
+
function processData(data: any) {
|
|
10
|
+
return data.value; // Loss of type safety
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// ✅ unknown + type guard
|
|
14
|
+
function processData(data: unknown) {
|
|
15
|
+
if (isValidData(data)) {
|
|
16
|
+
return data.value; // Type safe
|
|
17
|
+
}
|
|
18
|
+
throw new Error('Invalid data');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isValidData(data: unknown): data is { value: string } {
|
|
22
|
+
return typeof data === 'object' && data !== null && 'value' in data;
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2. Forced Type Casting with as any
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
// ❌ Bypassing types with as any
|
|
30
|
+
const user = response as any;
|
|
31
|
+
user.name; // Runtime error risk
|
|
32
|
+
|
|
33
|
+
// ✅ Proper type definition
|
|
34
|
+
interface User {
|
|
35
|
+
name: string;
|
|
36
|
+
email: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const user = response as User;
|
|
40
|
+
user.name; // Type safe
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 3. Overusing @ts-ignore
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// ❌ Ignoring errors with @ts-ignore
|
|
47
|
+
// @ts-ignore
|
|
48
|
+
const result = problematicCode();
|
|
49
|
+
|
|
50
|
+
// ✅ Fix the type issue at its root
|
|
51
|
+
interface Expected {
|
|
52
|
+
id: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const result: Expected = {
|
|
56
|
+
id: String(problematicCode()),
|
|
57
|
+
};
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## React Anti-Patterns
|
|
61
|
+
|
|
62
|
+
### 1. Using dangerouslySetInnerHTML
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// ❌ XSS vulnerability
|
|
66
|
+
function Component({ html }: { html: string }) {
|
|
67
|
+
return <div dangerouslySetInnerHTML={{ __html: html }} />;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ✅ Safe rendering
|
|
71
|
+
import DOMPurify from 'dompurify';
|
|
72
|
+
|
|
73
|
+
function Component({ html }: { html: string }) {
|
|
74
|
+
const sanitized = DOMPurify.sanitize(html);
|
|
75
|
+
return <div dangerouslySetInnerHTML={{ __html: sanitized }} />;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ✅ Better approach: Use markdown library
|
|
79
|
+
import ReactMarkdown from 'react-markdown';
|
|
80
|
+
|
|
81
|
+
function Component({ markdown }: { markdown: string }) {
|
|
82
|
+
return <ReactMarkdown>{markdown}</ReactMarkdown>;
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 2. Props Drilling (More than 3 levels)
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
// ❌ Props drilling
|
|
90
|
+
function App() {
|
|
91
|
+
const [user, setUser] = useState<User>();
|
|
92
|
+
return <Parent user={user} />;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function Parent({ user }: { user: User }) {
|
|
96
|
+
return <Child user={user} />;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function Child({ user }: { user: User }) {
|
|
100
|
+
return <GrandChild user={user} />;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function GrandChild({ user }: { user: User }) {
|
|
104
|
+
return <div>{user.name}</div>;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ✅ Use Context API
|
|
108
|
+
const UserContext = createContext<User | undefined>(undefined);
|
|
109
|
+
|
|
110
|
+
function App() {
|
|
111
|
+
const [user, setUser] = useState<User>();
|
|
112
|
+
return (
|
|
113
|
+
<UserContext.Provider value={user}>
|
|
114
|
+
<Parent />
|
|
115
|
+
</UserContext.Provider>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function GrandChild() {
|
|
120
|
+
const user = useContext(UserContext);
|
|
121
|
+
return <div>{user?.name}</div>;
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 3. Missing useEffect Dependency Array
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
// ❌ Missing dependency
|
|
129
|
+
function Component({ userId }: { userId: string }) {
|
|
130
|
+
const [user, setUser] = useState<User>();
|
|
131
|
+
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
fetchUser(userId).then(setUser);
|
|
134
|
+
}, []); // Missing userId dependency!
|
|
135
|
+
|
|
136
|
+
return <div>{user?.name}</div>;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ✅ Specify all dependencies
|
|
140
|
+
function Component({ userId }: { userId: string }) {
|
|
141
|
+
const [user, setUser] = useState<User>();
|
|
142
|
+
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
fetchUser(userId).then(setUser);
|
|
145
|
+
}, [userId]); // Dependency specified
|
|
146
|
+
|
|
147
|
+
return <div>{user?.name}</div>;
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## JavaScript Anti-Patterns
|
|
152
|
+
|
|
153
|
+
### 1. Using var
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
// ❌ Using var
|
|
157
|
+
var count = 0;
|
|
158
|
+
if (true) {
|
|
159
|
+
var count = 1; // Same variable!
|
|
160
|
+
}
|
|
161
|
+
console.log(count); // 1
|
|
162
|
+
|
|
163
|
+
// ✅ Use const/let
|
|
164
|
+
let count = 0;
|
|
165
|
+
if (true) {
|
|
166
|
+
let count = 1; // Block scope
|
|
167
|
+
}
|
|
168
|
+
console.log(count); // 0
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### 2. Using == (Loose Comparison)
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
// ❌ Using ==
|
|
175
|
+
if (value == null) { } // Also matches undefined
|
|
176
|
+
if ('5' == 5) { } // true (type coercion)
|
|
177
|
+
|
|
178
|
+
// ✅ Use ===
|
|
179
|
+
if (value === null) { }
|
|
180
|
+
if (value === undefined) { }
|
|
181
|
+
if ('5' === 5) { } // false
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 3. Using eval()
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
// ❌ Using eval() (security risk)
|
|
188
|
+
const code = userInput;
|
|
189
|
+
eval(code); // Can execute arbitrary code
|
|
190
|
+
|
|
191
|
+
// ✅ Alternative implementation
|
|
192
|
+
const allowedOperations = {
|
|
193
|
+
add: (a: number, b: number) => a + b,
|
|
194
|
+
subtract: (a: number, b: number) => a - b,
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const operation = allowedOperations[userInput];
|
|
198
|
+
if (operation) {
|
|
199
|
+
result = operation(a, b);
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## CSS Anti-Patterns
|
|
204
|
+
|
|
205
|
+
### 1. Overusing !important
|
|
206
|
+
|
|
207
|
+
```css
|
|
208
|
+
/* ❌ Overusing !important */
|
|
209
|
+
.button {
|
|
210
|
+
color: blue !important;
|
|
211
|
+
background: red !important;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/* ✅ Use specific selectors */
|
|
215
|
+
.navigation .button.primary {
|
|
216
|
+
color: blue;
|
|
217
|
+
background: red;
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### 2. Overusing Inline Styles
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
// ❌ Inline styles
|
|
225
|
+
function Button() {
|
|
226
|
+
return (
|
|
227
|
+
<button
|
|
228
|
+
style={{
|
|
229
|
+
backgroundColor: 'blue',
|
|
230
|
+
color: 'white',
|
|
231
|
+
padding: '10px',
|
|
232
|
+
borderRadius: '5px',
|
|
233
|
+
}}
|
|
234
|
+
>
|
|
235
|
+
Click me
|
|
236
|
+
</button>
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// ✅ Use CSS classes
|
|
241
|
+
function Button() {
|
|
242
|
+
return <button className="btn-primary">Click me</button>;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// styles.css
|
|
246
|
+
.btn-primary {
|
|
247
|
+
background-color: blue;
|
|
248
|
+
color: white;
|
|
249
|
+
padding: 10px;
|
|
250
|
+
border-radius: 5px;
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Performance Anti-Patterns
|
|
255
|
+
|
|
256
|
+
### 1. Unnecessary Re-renders
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
// ❌ Creating new objects/functions every render
|
|
260
|
+
function Parent() {
|
|
261
|
+
return <Child config={{ theme: 'dark' }} onClick={() => {}} />;
|
|
262
|
+
// New object/function created every render → Child re-renders
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// ✅ Use useMemo/useCallback
|
|
266
|
+
function Parent() {
|
|
267
|
+
const config = useMemo(() => ({ theme: 'dark' }), []);
|
|
268
|
+
const handleClick = useCallback(() => {}, []);
|
|
269
|
+
|
|
270
|
+
return <Child config={config} onClick={handleClick} />;
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### 2. Synchronous Heavy Computations
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
// ❌ Blocking main thread
|
|
278
|
+
function Component({ data }: { data: number[] }) {
|
|
279
|
+
const result = data
|
|
280
|
+
.map(heavyComputation)
|
|
281
|
+
.filter(x => x > 0)
|
|
282
|
+
.reduce((a, b) => a + b);
|
|
283
|
+
|
|
284
|
+
return <div>{result}</div>;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// ✅ Memoization with useMemo
|
|
288
|
+
function Component({ data }: { data: number[] }) {
|
|
289
|
+
const result = useMemo(
|
|
290
|
+
() =>
|
|
291
|
+
data
|
|
292
|
+
.map(heavyComputation)
|
|
293
|
+
.filter(x => x > 0)
|
|
294
|
+
.reduce((a, b) => a + b),
|
|
295
|
+
[data]
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
return <div>{result}</div>;
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## Security Anti-Patterns
|
|
303
|
+
|
|
304
|
+
### 1. Hardcoding Sensitive Information
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
// ❌ Hardcoded API key
|
|
308
|
+
const API_KEY = 'sk-1234567890abcdef';
|
|
309
|
+
|
|
310
|
+
// ✅ Use environment variables
|
|
311
|
+
const API_KEY = process.env.NEXT_PUBLIC_API_KEY;
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### 2. SQL Injection Vulnerability
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
// ❌ Direct string concatenation
|
|
318
|
+
const query = `SELECT * FROM users WHERE id = ${userId}`;
|
|
319
|
+
|
|
320
|
+
// ✅ Parameterized query
|
|
321
|
+
const query = 'SELECT * FROM users WHERE id = ?';
|
|
322
|
+
db.execute(query, [userId]);
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## Immutability Anti-Patterns
|
|
326
|
+
|
|
327
|
+
### 1. Direct State Mutation
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
// ❌ Directly mutating state
|
|
331
|
+
const [user, setUser] = useState({ name: 'John', age: 30 });
|
|
332
|
+
|
|
333
|
+
function updateAge() {
|
|
334
|
+
user.age = 31; // Direct mutation!
|
|
335
|
+
setUser(user); // React won't detect the change
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// ✅ Use spread operator for immutable update
|
|
339
|
+
function updateAge() {
|
|
340
|
+
setUser({ ...user, age: 31 }); // New object created
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// ✅ Or use functional update
|
|
344
|
+
function updateAge() {
|
|
345
|
+
setUser(prev => ({ ...prev, age: prev.age + 1 }));
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### 2. Array Mutation Methods
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
// ❌ Mutating array methods
|
|
353
|
+
const [items, setItems] = useState(['a', 'b', 'c']);
|
|
354
|
+
|
|
355
|
+
function addItem(item: string) {
|
|
356
|
+
items.push(item); // Mutates original array!
|
|
357
|
+
setItems(items);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function removeItem(index: number) {
|
|
361
|
+
items.splice(index, 1); // Mutates original array!
|
|
362
|
+
setItems(items);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// ✅ Immutable array operations
|
|
366
|
+
function addItem(item: string) {
|
|
367
|
+
setItems([...items, item]); // Spread creates new array
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function removeItem(index: number) {
|
|
371
|
+
setItems(items.filter((_, i) => i !== index)); // filter returns new array
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function updateItem(index: number, newValue: string) {
|
|
375
|
+
setItems(items.map((item, i) => i === index ? newValue : item));
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### 3. Nested Object Mutation
|
|
380
|
+
|
|
381
|
+
```typescript
|
|
382
|
+
// ❌ Deeply nested mutation
|
|
383
|
+
const [state, setState] = useState({
|
|
384
|
+
user: {
|
|
385
|
+
profile: {
|
|
386
|
+
name: 'John',
|
|
387
|
+
settings: { theme: 'dark' }
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
function updateTheme(theme: string) {
|
|
393
|
+
state.user.profile.settings.theme = theme; // Deep mutation!
|
|
394
|
+
setState(state);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// ✅ Immutable deep update
|
|
398
|
+
function updateTheme(theme: string) {
|
|
399
|
+
setState({
|
|
400
|
+
...state,
|
|
401
|
+
user: {
|
|
402
|
+
...state.user,
|
|
403
|
+
profile: {
|
|
404
|
+
...state.user.profile,
|
|
405
|
+
settings: {
|
|
406
|
+
...state.user.profile.settings,
|
|
407
|
+
theme
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// ✅ Better: Use immer for complex updates
|
|
415
|
+
import { produce } from 'immer';
|
|
416
|
+
|
|
417
|
+
function updateTheme(theme: string) {
|
|
418
|
+
setState(produce(draft => {
|
|
419
|
+
draft.user.profile.settings.theme = theme; // Safe with immer
|
|
420
|
+
}));
|
|
421
|
+
}
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### 4. Object.assign Misuse
|
|
425
|
+
|
|
426
|
+
```typescript
|
|
427
|
+
// ❌ Object.assign mutating first argument
|
|
428
|
+
const original = { a: 1, b: 2 };
|
|
429
|
+
const updated = Object.assign(original, { b: 3 }); // Mutates original!
|
|
430
|
+
|
|
431
|
+
// ✅ Use empty object as first argument
|
|
432
|
+
const updated = Object.assign({}, original, { b: 3 });
|
|
433
|
+
|
|
434
|
+
// ✅ Or use spread (preferred)
|
|
435
|
+
const updated = { ...original, b: 3 };
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### 5. Reducer State Mutation
|
|
439
|
+
|
|
440
|
+
```typescript
|
|
441
|
+
// ❌ Mutating state in reducer
|
|
442
|
+
function reducer(state: State, action: Action) {
|
|
443
|
+
switch (action.type) {
|
|
444
|
+
case 'ADD_ITEM':
|
|
445
|
+
state.items.push(action.payload); // Mutation!
|
|
446
|
+
return state;
|
|
447
|
+
default:
|
|
448
|
+
return state;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// ✅ Return new state
|
|
453
|
+
function reducer(state: State, action: Action) {
|
|
454
|
+
switch (action.type) {
|
|
455
|
+
case 'ADD_ITEM':
|
|
456
|
+
return {
|
|
457
|
+
...state,
|
|
458
|
+
items: [...state.items, action.payload]
|
|
459
|
+
};
|
|
460
|
+
default:
|
|
461
|
+
return state;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
### 6. Mutating Function Parameters
|
|
467
|
+
|
|
468
|
+
```typescript
|
|
469
|
+
// ❌ Mutating input parameter
|
|
470
|
+
function addTimestamp(data: Record<string, unknown>) {
|
|
471
|
+
data.timestamp = Date.now(); // Mutates caller's object!
|
|
472
|
+
return data;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// ✅ Create new object
|
|
476
|
+
function addTimestamp(data: Record<string, unknown>) {
|
|
477
|
+
return {
|
|
478
|
+
...data,
|
|
479
|
+
timestamp: Date.now()
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
### Immutable Methods Reference
|
|
485
|
+
|
|
486
|
+
| Mutating (Avoid) | Immutable (Use) |
|
|
487
|
+
|------------------|-----------------|
|
|
488
|
+
| `push()` | `[...arr, item]` |
|
|
489
|
+
| `pop()` | `arr.slice(0, -1)` |
|
|
490
|
+
| `shift()` | `arr.slice(1)` |
|
|
491
|
+
| `unshift()` | `[item, ...arr]` |
|
|
492
|
+
| `splice()` | `filter()` / `slice()` + spread |
|
|
493
|
+
| `sort()` | `[...arr].sort()` |
|
|
494
|
+
| `reverse()` | `[...arr].reverse()` |
|
|
495
|
+
| `obj.prop = x` | `{ ...obj, prop: x }` |
|
|
496
|
+
|
|
497
|
+
## Error Handling Anti-Patterns
|
|
498
|
+
|
|
499
|
+
### 1. Empty catch Block
|
|
500
|
+
|
|
501
|
+
```typescript
|
|
502
|
+
// ❌ Ignoring errors
|
|
503
|
+
try {
|
|
504
|
+
riskyOperation();
|
|
505
|
+
} catch (e) {
|
|
506
|
+
// Does nothing
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// ✅ Proper error handling
|
|
510
|
+
try {
|
|
511
|
+
riskyOperation();
|
|
512
|
+
} catch (error) {
|
|
513
|
+
console.error('Operation failed:', error);
|
|
514
|
+
showErrorNotification(error);
|
|
515
|
+
trackError(error);
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### 2. Handling Without Error Type Check
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
// ❌ Treating all errors the same
|
|
523
|
+
try {
|
|
524
|
+
await fetchData();
|
|
525
|
+
} catch (error) {
|
|
526
|
+
showError('Failed'); // Not specific
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// ✅ Handle by error type
|
|
530
|
+
try {
|
|
531
|
+
await fetchData();
|
|
532
|
+
} catch (error) {
|
|
533
|
+
if (error instanceof NetworkError) {
|
|
534
|
+
showError('Please check your network connection');
|
|
535
|
+
} else if (error instanceof AuthError) {
|
|
536
|
+
redirectToLogin();
|
|
537
|
+
} else {
|
|
538
|
+
showError('An unknown error occurred');
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
```
|