ima-claude 2.9.0
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/LICENSE +21 -0
- package/README.md +463 -0
- package/dist/cli.js +1064 -0
- package/package.json +49 -0
- package/platforms/claude/adapter.ts +115 -0
- package/platforms/junie/adapter.ts +254 -0
- package/platforms/junie/agents-template.md +113 -0
- package/platforms/junie/hook-translations.md +84 -0
- package/platforms/shared/detector.ts +27 -0
- package/platforms/shared/installer.ts +202 -0
- package/platforms/shared/types.ts +78 -0
- package/plugins/ima-claude/.claude-plugin/plugin.json +25 -0
- package/plugins/ima-claude/agents/explorer.md +30 -0
- package/plugins/ima-claude/agents/implementer.md +30 -0
- package/plugins/ima-claude/agents/memory.md +42 -0
- package/plugins/ima-claude/agents/reviewer.md +53 -0
- package/plugins/ima-claude/agents/tester.md +33 -0
- package/plugins/ima-claude/agents/wp-developer.md +46 -0
- package/plugins/ima-claude/hooks/README.md +145 -0
- package/plugins/ima-claude/hooks/atlassian_prereqs.py +112 -0
- package/plugins/ima-claude/hooks/block_sed_edits.py +59 -0
- package/plugins/ima-claude/hooks/bootstrap.sh +90 -0
- package/plugins/ima-claude/hooks/bootstrap_utility_check.py +94 -0
- package/plugins/ima-claude/hooks/composer_autoload_check.py +70 -0
- package/plugins/ima-claude/hooks/docs_organization.py +104 -0
- package/plugins/ima-claude/hooks/enforce_rg_over_grep.py +56 -0
- package/plugins/ima-claude/hooks/fp_utility_check.py +90 -0
- package/plugins/ima-claude/hooks/hook_logger.py +69 -0
- package/plugins/ima-claude/hooks/hooks.json +239 -0
- package/plugins/ima-claude/hooks/jira_issue_fetch.py +79 -0
- package/plugins/ima-claude/hooks/jquery_in_wordpress.py +92 -0
- package/plugins/ima-claude/hooks/memory_bootstrap.py +79 -0
- package/plugins/ima-claude/hooks/memory_store_reminder.py +75 -0
- package/plugins/ima-claude/hooks/prompt_coach.py +125 -0
- package/plugins/ima-claude/hooks/prompt_coach_digest.md +48 -0
- package/plugins/ima-claude/hooks/prompt_coach_system.md +30 -0
- package/plugins/ima-claude/hooks/sequential_thinking_check.py +81 -0
- package/plugins/ima-claude/hooks/serena_over_grep.py +96 -0
- package/plugins/ima-claude/hooks/serena_over_read.py +66 -0
- package/plugins/ima-claude/hooks/serena_project_check.py +133 -0
- package/plugins/ima-claude/hooks/sql_injection_check.py +73 -0
- package/plugins/ima-claude/hooks/task_master_after_plan.py +31 -0
- package/plugins/ima-claude/hooks/task_master_before_impl.py +93 -0
- package/plugins/ima-claude/hooks/tavily_extract_advanced.py +48 -0
- package/plugins/ima-claude/hooks/vestige_before_external.py +86 -0
- package/plugins/ima-claude/hooks/webfetch_to_tavily.py +42 -0
- package/plugins/ima-claude/hooks/websearch_to_tavily.py +41 -0
- package/plugins/ima-claude/hooks/wp_security_check.py +150 -0
- package/plugins/ima-claude/personalities/README.md +45 -0
- package/plugins/ima-claude/personalities/enable-40k.md +69 -0
- package/plugins/ima-claude/personalities/enable-templars.md +69 -0
- package/plugins/ima-claude/skills/.research-summary.md +340 -0
- package/plugins/ima-claude/skills/architect/SKILL.md +304 -0
- package/plugins/ima-claude/skills/compound-bridge/SKILL.md +200 -0
- package/plugins/ima-claude/skills/discourse/SKILL.md +440 -0
- package/plugins/ima-claude/skills/discourse-admin/SKILL.md +192 -0
- package/plugins/ima-claude/skills/discourse-admin/references/api-endpoints.md +441 -0
- package/plugins/ima-claude/skills/discourse-admin/references/gotchas.md +107 -0
- package/plugins/ima-claude/skills/discourse-admin/references/staging-defaults.md +98 -0
- package/plugins/ima-claude/skills/discourse-admin/scripts/discourse-admin.py +319 -0
- package/plugins/ima-claude/skills/docs-organize/SKILL.md +254 -0
- package/plugins/ima-claude/skills/docs-organize/templates/active-README.md +50 -0
- package/plugins/ima-claude/skills/docs-organize/templates/archive-README.md +57 -0
- package/plugins/ima-claude/skills/docs-organize/templates/docs-README.md +43 -0
- package/plugins/ima-claude/skills/docs-organize/templates/phase-archive-README.md +83 -0
- package/plugins/ima-claude/skills/docs-organize/templates/section-README.md +48 -0
- package/plugins/ima-claude/skills/docs-organize/templates/transient-README.md +79 -0
- package/plugins/ima-claude/skills/docs-organize/templates/transient-gitignore +9 -0
- package/plugins/ima-claude/skills/ember-discourse/SKILL.md +496 -0
- package/plugins/ima-claude/skills/functional-programmer/SKILL.md +258 -0
- package/plugins/ima-claude/skills/ima-bootstrap/SKILL.md +278 -0
- package/plugins/ima-claude/skills/ima-bootstrap/references/bootstrap-patterns.md +356 -0
- package/plugins/ima-claude/skills/ima-bootstrap/references/ima-brand.md +273 -0
- package/plugins/ima-claude/skills/ima-bootstrap/references/theme-integration.md +212 -0
- package/plugins/ima-claude/skills/ima-brand/SKILL.md +108 -0
- package/plugins/ima-claude/skills/ima-brand/references/brand-identity.md +140 -0
- package/plugins/ima-claude/skills/ima-brand/references/digital-standards.md +180 -0
- package/plugins/ima-claude/skills/ima-brand/references/visual-system.md +173 -0
- package/plugins/ima-claude/skills/ima-forms-expert/SKILL.md +175 -0
- package/plugins/ima-claude/skills/ima-forms-expert/references/container-components.md +154 -0
- package/plugins/ima-claude/skills/ima-forms-expert/references/examples.md +328 -0
- package/plugins/ima-claude/skills/ima-forms-expert/references/field-components.md +298 -0
- package/plugins/ima-claude/skills/ima-forms-expert/references/form-factory.md +193 -0
- package/plugins/ima-claude/skills/ima-forms-expert/references/quick-reference.md +153 -0
- package/plugins/ima-claude/skills/ima-forms-expert/references/validation-engine.md +336 -0
- package/plugins/ima-claude/skills/jira-checkpoint/SKILL.md +178 -0
- package/plugins/ima-claude/skills/jquery/SKILL.md +413 -0
- package/plugins/ima-claude/skills/js-fp/SKILL.md +463 -0
- package/plugins/ima-claude/skills/js-fp/core-principles.md +487 -0
- package/plugins/ima-claude/skills/js-fp/examples/pure-functions.js +260 -0
- package/plugins/ima-claude/skills/js-fp/examples/tests/pure-functions.test.js +262 -0
- package/plugins/ima-claude/skills/js-fp/references/anti-patterns.md +120 -0
- package/plugins/ima-claude/skills/js-fp/references/performance-patterns.md +116 -0
- package/plugins/ima-claude/skills/js-fp/references/testing-patterns.md +134 -0
- package/plugins/ima-claude/skills/js-fp-api/SKILL.md +280 -0
- package/plugins/ima-claude/skills/js-fp-api/examples/crud-endpoint.js +258 -0
- package/plugins/ima-claude/skills/js-fp-api/references/middleware-patterns.md +134 -0
- package/plugins/ima-claude/skills/js-fp-api/references/security-sql.md +110 -0
- package/plugins/ima-claude/skills/js-fp-api/references/validation-patterns.md +165 -0
- package/plugins/ima-claude/skills/js-fp-react/SKILL.md +447 -0
- package/plugins/ima-claude/skills/js-fp-react/examples/ProductCard.tsx +65 -0
- package/plugins/ima-claude/skills/js-fp-react/references/hooks-advanced.md +136 -0
- package/plugins/ima-claude/skills/js-fp-react/references/performance-patterns.md +175 -0
- package/plugins/ima-claude/skills/js-fp-vue/SKILL.md +322 -0
- package/plugins/ima-claude/skills/js-fp-vue/references/complete-examples.md +397 -0
- package/plugins/ima-claude/skills/js-fp-vue/references/composables-advanced.md +282 -0
- package/plugins/ima-claude/skills/js-fp-vue/references/reactivity-patterns.md +348 -0
- package/plugins/ima-claude/skills/js-fp-vue/references/testing.md +314 -0
- package/plugins/ima-claude/skills/js-fp-wordpress/SKILL.md +301 -0
- package/plugins/ima-claude/skills/js-fp-wordpress/references/ajax-patterns.md +192 -0
- package/plugins/ima-claude/skills/js-fp-wordpress/references/event-patterns.md +136 -0
- package/plugins/ima-claude/skills/js-fp-wordpress/references/wp-integration.md +248 -0
- package/plugins/ima-claude/skills/livecanvas/SKILL.md +209 -0
- package/plugins/ima-claude/skills/livecanvas/references/livecanvas-features.md +311 -0
- package/plugins/ima-claude/skills/livecanvas/references/loops-and-logic.md +730 -0
- package/plugins/ima-claude/skills/livecanvas/references/picostrap.md +227 -0
- package/plugins/ima-claude/skills/mcp-atlassian/SKILL.md +339 -0
- package/plugins/ima-claude/skills/mcp-context7/SKILL.md +109 -0
- package/plugins/ima-claude/skills/mcp-memory/SKILL.md +182 -0
- package/plugins/ima-claude/skills/mcp-qdrant/SKILL.md +233 -0
- package/plugins/ima-claude/skills/mcp-sequential/SKILL.md +149 -0
- package/plugins/ima-claude/skills/mcp-serena/SKILL.md +174 -0
- package/plugins/ima-claude/skills/mcp-tavily/SKILL.md +118 -0
- package/plugins/ima-claude/skills/mcp-vestige/SKILL.md +259 -0
- package/plugins/ima-claude/skills/php-authnet/SKILL.md +275 -0
- package/plugins/ima-claude/skills/php-authnet/references/api-reference.md +624 -0
- package/plugins/ima-claude/skills/php-authnet/references/sandbox-testing.md +424 -0
- package/plugins/ima-claude/skills/php-fp/SKILL.md +333 -0
- package/plugins/ima-claude/skills/php-fp/examples/pure-functions.php +403 -0
- package/plugins/ima-claude/skills/php-fp/examples/tests/PureFunctionsTest.php +515 -0
- package/plugins/ima-claude/skills/php-fp/references/core-principles.md +277 -0
- package/plugins/ima-claude/skills/php-fp/references/testing-patterns.md +374 -0
- package/plugins/ima-claude/skills/php-fp-wordpress/SKILL.md +216 -0
- package/plugins/ima-claude/skills/php-fp-wordpress/references/fp-patterns.md +275 -0
- package/plugins/ima-claude/skills/php-fp-wordpress/references/plugin-architecture.md +295 -0
- package/plugins/ima-claude/skills/php-fp-wordpress/references/security-examples.md +203 -0
- package/plugins/ima-claude/skills/php-fp-wordpress/references/testing-strategy.md +259 -0
- package/plugins/ima-claude/skills/phpunit-wp/SKILL.md +716 -0
- package/plugins/ima-claude/skills/playwright/SKILL.md +434 -0
- package/plugins/ima-claude/skills/playwright/references/accessibility-testing.md +153 -0
- package/plugins/ima-claude/skills/playwright/references/ci-cd.md +268 -0
- package/plugins/ima-claude/skills/playwright/references/network-mocking.md +270 -0
- package/plugins/ima-claude/skills/playwright/references/visual-regression.md +215 -0
- package/plugins/ima-claude/skills/py-fp/SKILL.md +663 -0
- package/plugins/ima-claude/skills/py-fp/examples/pure-functions.py +185 -0
- package/plugins/ima-claude/skills/py-fp/examples/tests/test_pure_functions.py +244 -0
- package/plugins/ima-claude/skills/py-fp/references/core-principles.md +381 -0
- package/plugins/ima-claude/skills/py-fp/references/testing-patterns.md +283 -0
- package/plugins/ima-claude/skills/quasar-fp/SKILL.md +327 -0
- package/plugins/ima-claude/skills/quasar-fp/metadata.json +85 -0
- package/plugins/ima-claude/skills/quasar-fp/references/component-patterns.md +257 -0
- package/plugins/ima-claude/skills/quasar-fp/references/theme-integration.md +233 -0
- package/plugins/ima-claude/skills/quasar-fp/references/utility-classes.md +237 -0
- package/plugins/ima-claude/skills/quickstart/SKILL.md +129 -0
- package/plugins/ima-claude/skills/rails/SKILL.md +359 -0
- package/plugins/ima-claude/skills/resume-session/SKILL.md +68 -0
- package/plugins/ima-claude/skills/rg/SKILL.md +205 -0
- package/plugins/ima-claude/skills/ruby-fp/SKILL.md +336 -0
- package/plugins/ima-claude/skills/save-session/SKILL.md +81 -0
- package/plugins/ima-claude/skills/scorecard/SKILL.md +96 -0
- package/plugins/ima-claude/skills/skill-analyzer/SKILL.md +127 -0
- package/plugins/ima-claude/skills/skill-analyzer/references/advanced-checklist.md +44 -0
- package/plugins/ima-claude/skills/skill-analyzer/references/core-checklist.md +60 -0
- package/plugins/ima-claude/skills/skill-analyzer/scripts/analyze_skill.py +418 -0
- package/plugins/ima-claude/skills/skill-creator/LICENSE.txt +202 -0
- package/plugins/ima-claude/skills/skill-creator/SKILL.md +343 -0
- package/plugins/ima-claude/skills/skill-creator/references/output-patterns.md +82 -0
- package/plugins/ima-claude/skills/skill-creator/references/workflows.md +28 -0
- package/plugins/ima-claude/skills/skill-creator/scripts/init_skill.py +303 -0
- package/plugins/ima-claude/skills/skill-creator/scripts/package_skill.py +110 -0
- package/plugins/ima-claude/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/plugins/ima-claude/skills/task-master/SKILL.md +51 -0
- package/plugins/ima-claude/skills/task-planner/SKILL.md +228 -0
- package/plugins/ima-claude/skills/task-runner/SKILL.md +192 -0
- package/plugins/ima-claude/skills/unit-testing/SKILL.md +198 -0
- package/plugins/ima-claude/skills/unit-testing/references/mock-patterns.md +181 -0
- package/plugins/ima-claude/skills/unit-testing/references/tdd-workflow.md +177 -0
- package/plugins/ima-claude/skills/unit-testing/references/test-strategy.md +126 -0
- package/plugins/ima-claude/skills/wp-local/SKILL.md +246 -0
- package/plugins/ima-claude/skills/wp-local/references/configuration.md +198 -0
- package/plugins/ima-claude/skills/wp-local/references/wp-cli-reference.md +406 -0
- package/plugins/ima-claude/skills/wp-local/scripts/wp-local.sh +61 -0
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "js-fp"
|
|
3
|
+
description: "Core FP principles with anti-over-engineering focus - Simple > Complex | Evidence > Assumptions"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# JavaScript Functional Programming
|
|
7
|
+
|
|
8
|
+
Core functional programming principles for JavaScript with anti-over-engineering enforcement. This skill provides error-preventing essentials and references to deep-dive content.
|
|
9
|
+
|
|
10
|
+
## When to Use This Skill
|
|
11
|
+
|
|
12
|
+
- Implementing pure, testable functions
|
|
13
|
+
- Need FP architectural guidance
|
|
14
|
+
- Preventing over-engineering and custom FP utility creation
|
|
15
|
+
- Comprehensive testing strategies
|
|
16
|
+
- Evidence-based performance optimization
|
|
17
|
+
|
|
18
|
+
## ⚠️ CRITICAL: Anti-Over-Engineering (PRIMARY FOCUS)
|
|
19
|
+
|
|
20
|
+
**Core Principle**: "Simple > Complex | Evidence > Assumptions"
|
|
21
|
+
|
|
22
|
+
> **Clarification**: This skill prevents CREATING custom FP utility functions (pipe, compose, curry) to make JavaScript "feel" like Haskell. Using established libraries (lodash, date-fns, etc.) is perfectly fine. FP is a mindset—pure functions, immutability, composition—not a rigid API signature.
|
|
23
|
+
|
|
24
|
+
### Don't Create Custom FP Utilities
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
// ❌ DON'T CREATE: pipe() utility
|
|
28
|
+
const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x)
|
|
29
|
+
|
|
30
|
+
// ✅ INSTEAD: Native function calls with early returns
|
|
31
|
+
const validateUser = (userData) => {
|
|
32
|
+
const requiredCheck = validateRequired(['email', 'name'])(userData)
|
|
33
|
+
if (!requiredCheck.valid) return requiredCheck
|
|
34
|
+
|
|
35
|
+
const emailCheck = validateEmail(userData)
|
|
36
|
+
if (!emailCheck.valid) return emailCheck
|
|
37
|
+
|
|
38
|
+
return validateNameLength(userData)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ❌ DON'T CREATE: compose() utility
|
|
42
|
+
const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x)
|
|
43
|
+
|
|
44
|
+
// ✅ INSTEAD: Direct function calls
|
|
45
|
+
const processData = (raw) => {
|
|
46
|
+
const normalized = normalize(raw)
|
|
47
|
+
const validated = validate(normalized)
|
|
48
|
+
return transform(validated)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ❌ DON'T CREATE: curry() utility
|
|
52
|
+
const curry = (fn) => (...args) => args.length >= fn.length
|
|
53
|
+
? fn(...args)
|
|
54
|
+
: (...more) => curry(fn)(...args, ...more)
|
|
55
|
+
|
|
56
|
+
// ✅ INSTEAD: Native closures and function factories
|
|
57
|
+
const createValidator = (rules) => (value) => {
|
|
58
|
+
const errors = rules.filter(rule => !rule.validator(value))
|
|
59
|
+
return errors.length === 0 ? { valid: true } : { valid: false, errors }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ❌ DON'T CREATE: Custom monads
|
|
63
|
+
class Maybe { /* complex monad implementation */ }
|
|
64
|
+
|
|
65
|
+
// ✅ INSTEAD: Native error handling and conditionals
|
|
66
|
+
const getUser = async (id) => {
|
|
67
|
+
try {
|
|
68
|
+
const user = await fetchUser(id)
|
|
69
|
+
return { success: true, data: user }
|
|
70
|
+
} catch (error) {
|
|
71
|
+
return { success: false, error: error.message }
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Context-Appropriate Complexity
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
// CLI Script: Simple and direct
|
|
80
|
+
const processFile = (filePath) => {
|
|
81
|
+
const data = readFileSync(filePath, 'utf8')
|
|
82
|
+
const lines = data.split('\n').filter(line => line.trim())
|
|
83
|
+
return lines.map(line => line.toUpperCase())
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Production Service: Appropriate error handling
|
|
87
|
+
const processFile = async (filePath, logger) => {
|
|
88
|
+
try {
|
|
89
|
+
const data = await readFile(filePath, 'utf8')
|
|
90
|
+
const lines = data.split('\n').filter(line => line.trim())
|
|
91
|
+
logger.info('File processed', { filePath, lineCount: lines.length })
|
|
92
|
+
return { success: true, data: lines.map(line => line.toUpperCase()) }
|
|
93
|
+
} catch (error) {
|
|
94
|
+
logger.error('File processing failed', { filePath, error })
|
|
95
|
+
return { success: false, error: error.message }
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Big Data System: Performance optimization with evidence
|
|
100
|
+
const createFileProcessor = (config) => {
|
|
101
|
+
// Pre-compile expensive transformations
|
|
102
|
+
const transformers = config.transforms.map(compileTransformer)
|
|
103
|
+
|
|
104
|
+
return async (filePath, logger) => {
|
|
105
|
+
const stream = createReadStream(filePath)
|
|
106
|
+
return processStream(stream, transformers, logger)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Core FP Patterns (Error-Preventing Essentials)
|
|
112
|
+
|
|
113
|
+
### 1. Purity and Side Effect Isolation
|
|
114
|
+
|
|
115
|
+
**Rule**: Separate business logic from side effects.
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
// ❌ Impure - side effects mixed with logic
|
|
119
|
+
function calculateTotal(items) {
|
|
120
|
+
console.log('Processing items') // Side effect
|
|
121
|
+
total += items.reduce((sum, item) => sum + item.price, 0) // Mutation
|
|
122
|
+
return total
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ✅ Pure business logic
|
|
126
|
+
const calculateTotal = (items) =>
|
|
127
|
+
items.reduce((sum, item) => sum + item.price, 0)
|
|
128
|
+
|
|
129
|
+
// ✅ Side effects isolated
|
|
130
|
+
const logAndCalculate = (items, logger) => {
|
|
131
|
+
const total = calculateTotal(items) // Pure calculation
|
|
132
|
+
logger.log(`Total: ${total}`) // Side effect isolated
|
|
133
|
+
return total
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**Benefits**:
|
|
138
|
+
- 100% testable with all edge cases
|
|
139
|
+
- Predictable behavior and debugging
|
|
140
|
+
- Safe for parallel execution
|
|
141
|
+
- Enables optimization through memoization
|
|
142
|
+
|
|
143
|
+
### 2. Composition Over Inheritance
|
|
144
|
+
|
|
145
|
+
**Rule**: Build complex behavior from simple functions.
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
// ❌ Class hierarchy approach
|
|
149
|
+
class BaseValidator {
|
|
150
|
+
validate() { throw new Error('Not implemented') }
|
|
151
|
+
}
|
|
152
|
+
class EmailValidator extends BaseValidator {
|
|
153
|
+
validate(value) { /* email logic */ }
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ✅ Function composition (no utilities needed)
|
|
157
|
+
const validateRequired = (value) => value != null && value !== ''
|
|
158
|
+
const validateEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)
|
|
159
|
+
const validateLength = (min, max) => (value) =>
|
|
160
|
+
value.length >= min && value.length <= max
|
|
161
|
+
|
|
162
|
+
// Simple composition without pipe() utility
|
|
163
|
+
const validateUserEmail = (email) => {
|
|
164
|
+
if (!validateRequired(email)) return { valid: false, error: 'Required' }
|
|
165
|
+
if (!validateEmail(email)) return { valid: false, error: 'Invalid email' }
|
|
166
|
+
if (!validateLength(5, 100)(email)) return { valid: false, error: 'Length' }
|
|
167
|
+
return { valid: true }
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### 3. Dependency Injection Through Parameters
|
|
172
|
+
|
|
173
|
+
**Rule**: Pass dependencies explicitly, avoid global state.
|
|
174
|
+
|
|
175
|
+
```javascript
|
|
176
|
+
// ❌ Hidden dependencies, hard to test
|
|
177
|
+
function saveUser(userData) {
|
|
178
|
+
const hashedPassword = bcrypt.hash(userData.password) // Hidden
|
|
179
|
+
return database.save({ ...userData, password: hashedPassword }) // Hidden
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ✅ Explicit dependencies, fully testable
|
|
183
|
+
const saveUser = async (userData, hasher, database) => {
|
|
184
|
+
const hashedPassword = await hasher.hash(userData.password)
|
|
185
|
+
return database.save({ ...userData, password: hashedPassword })
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ✅ Function factory for repeated use
|
|
189
|
+
const createUserService = (hasher, database) => ({
|
|
190
|
+
saveUser: (userData) => saveUser(userData, hasher, database),
|
|
191
|
+
findUser: (id) => database.findById(id)
|
|
192
|
+
})
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### 4. Immutability Patterns
|
|
196
|
+
|
|
197
|
+
**Rule**: Avoid mutations, create new objects/arrays.
|
|
198
|
+
|
|
199
|
+
```javascript
|
|
200
|
+
// ❌ Mutation approach
|
|
201
|
+
function updateUserSettings(user, settings) {
|
|
202
|
+
user.settings = { ...user.settings, ...settings } // Mutates user
|
|
203
|
+
user.updatedAt = new Date()
|
|
204
|
+
return user
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// ✅ Immutable approach
|
|
208
|
+
const updateUserSettings = (user, settings) => ({
|
|
209
|
+
...user,
|
|
210
|
+
settings: { ...user.settings, ...settings },
|
|
211
|
+
updatedAt: new Date()
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
// ✅ Array operations without mutation
|
|
215
|
+
const addItem = (items, newItem) => [...items, newItem]
|
|
216
|
+
const removeItem = (items, id) => items.filter(item => item.id !== id)
|
|
217
|
+
const updateItem = (items, id, updates) =>
|
|
218
|
+
items.map(item => item.id === id ? { ...item, ...updates } : item)
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Testing Essentials (Enabled by Purity)
|
|
222
|
+
|
|
223
|
+
**Philosophy**: Pure functions enable testing all edge cases systematically.
|
|
224
|
+
|
|
225
|
+
```javascript
|
|
226
|
+
// Traditional testing (limited coverage)
|
|
227
|
+
describe('calculateDiscount', () => {
|
|
228
|
+
it('should calculate 10% discount', () => {
|
|
229
|
+
expect(calculateDiscount(100, 0.1)).toBe(10)
|
|
230
|
+
})
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
// FP comprehensive testing (all edge cases)
|
|
234
|
+
describe('calculateDiscount - FP Comprehensive', () => {
|
|
235
|
+
describe('valid inputs', () => {
|
|
236
|
+
const testCases = [
|
|
237
|
+
[100, 0.1, 10],
|
|
238
|
+
[50, 0.2, 10],
|
|
239
|
+
[0, 0.1, 0]
|
|
240
|
+
]
|
|
241
|
+
|
|
242
|
+
testCases.forEach(([price, rate, expected]) => {
|
|
243
|
+
it(`${rate*100}% discount on ${price} = ${expected}`, () => {
|
|
244
|
+
expect(calculateDiscount(price, rate)).toBe(expected)
|
|
245
|
+
})
|
|
246
|
+
})
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
describe('all data types - systematic edge cases', () => {
|
|
250
|
+
const invalidTypes = [null, undefined, NaN, true, [], {}, '100']
|
|
251
|
+
|
|
252
|
+
invalidTypes.forEach(input => {
|
|
253
|
+
it(`handles ${typeof input} gracefully`, () => {
|
|
254
|
+
expect(() => calculateDiscount(input, 0.1)).not.toThrow()
|
|
255
|
+
expect(calculateDiscount(input, 0.1)).toBe(0)
|
|
256
|
+
})
|
|
257
|
+
})
|
|
258
|
+
})
|
|
259
|
+
})
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## Performance Patterns (Evidence-Based)
|
|
263
|
+
|
|
264
|
+
**⚠️ IMPORTANT**: Optimize only when needed with evidence.
|
|
265
|
+
|
|
266
|
+
### Configuration Pre-Compilation (When Actually Needed)
|
|
267
|
+
|
|
268
|
+
**Use When**: Processing large datasets (>10K items) with repeated configuration access.
|
|
269
|
+
|
|
270
|
+
```javascript
|
|
271
|
+
// Problem: O(records × fields) complexity
|
|
272
|
+
function processRecords(records, schema) {
|
|
273
|
+
return records.map(record => {
|
|
274
|
+
return schema.fields.reduce((obj, field) => { // ← Repeated config access
|
|
275
|
+
obj[field.name] = transformField(record[field.name], field.type)
|
|
276
|
+
return obj
|
|
277
|
+
}, {})
|
|
278
|
+
})
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Solution: O(records + fields) - pre-compile configuration
|
|
282
|
+
function createRecordProcessor(schema) {
|
|
283
|
+
// Setup once - extract expensive configuration
|
|
284
|
+
const fieldProcessors = schema.fields.map(field =>
|
|
285
|
+
value => transformField(value, field.type)
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
return record => fieldProcessors.reduce((obj, processor, i) => {
|
|
289
|
+
obj[schema.fields[i].name] = processor(record[schema.fields[i].name])
|
|
290
|
+
return obj
|
|
291
|
+
}, {})
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Usage: Configuration cost paid once
|
|
295
|
+
const processor = createRecordProcessor(schema) // Setup phase
|
|
296
|
+
const results = records.map(processor) // Linear execution
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Function Factories for Reusable Logic
|
|
300
|
+
|
|
301
|
+
```javascript
|
|
302
|
+
// Create specialized functions instead of generic ones
|
|
303
|
+
const createValidator = (rules) => (value) => {
|
|
304
|
+
const errors = []
|
|
305
|
+
for (const rule of rules) {
|
|
306
|
+
if (!rule.validator(value)) {
|
|
307
|
+
errors.push(rule.message)
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return errors.length === 0 ? { valid: true } : { valid: false, errors }
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Usage: Configure once, use many times
|
|
314
|
+
const validateEmail = createValidator([
|
|
315
|
+
{ validator: v => typeof v === 'string', message: 'Must be string' },
|
|
316
|
+
{ validator: v => v.includes('@'), message: 'Must contain @' },
|
|
317
|
+
{ validator: v => v.length > 5, message: 'Too short' }
|
|
318
|
+
])
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## Language-Specific Idioms
|
|
322
|
+
|
|
323
|
+
### Native JavaScript Patterns
|
|
324
|
+
|
|
325
|
+
```javascript
|
|
326
|
+
// Native array methods over loops
|
|
327
|
+
const processUsers = (users) =>
|
|
328
|
+
users
|
|
329
|
+
.filter(user => user.active)
|
|
330
|
+
.map(user => ({ ...user, displayName: `${user.firstName} ${user.lastName}` }))
|
|
331
|
+
.sort((a, b) => a.lastName.localeCompare(b.lastName))
|
|
332
|
+
|
|
333
|
+
// Native async/await over callbacks
|
|
334
|
+
const fetchUserData = async (userId, fetcher) => {
|
|
335
|
+
try {
|
|
336
|
+
const user = await fetcher.getUser(userId)
|
|
337
|
+
const preferences = await fetcher.getPreferences(userId)
|
|
338
|
+
return { ...user, preferences }
|
|
339
|
+
} catch (error) {
|
|
340
|
+
return { error: error.message }
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// WeakMap for performance when appropriate
|
|
345
|
+
const createMemoized = () => {
|
|
346
|
+
const cache = new WeakMap()
|
|
347
|
+
return (obj, computeFn) => {
|
|
348
|
+
if (cache.has(obj)) return cache.get(obj)
|
|
349
|
+
const result = computeFn(obj)
|
|
350
|
+
cache.set(obj, result)
|
|
351
|
+
return result
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
## Quality Gates (Pre-Implementation Checklist)
|
|
357
|
+
|
|
358
|
+
1. **"Can this be pure?"** → Separate business logic from side effects
|
|
359
|
+
2. **"Can this use native patterns?"** → Avoid creating custom FP utilities, use language features
|
|
360
|
+
3. **"Can this be simplified?"** → Choose simple solution over complex abstraction
|
|
361
|
+
4. **"Is this complexity justified?"** → Evidence-based complexity decisions
|
|
362
|
+
5. **"Is this testable?"** → Pure functions enable comprehensive testing
|
|
363
|
+
6. **"Is this context-appropriate?"** → CLI script ≠ production service ≠ big data system
|
|
364
|
+
|
|
365
|
+
## When to Load Additional Content
|
|
366
|
+
|
|
367
|
+
### Deep Principles and Explanations
|
|
368
|
+
**File**: `core-principles.md` (~800 lines)
|
|
369
|
+
**When**: Learning mode, explaining WHY, architectural decisions
|
|
370
|
+
**Contains**: Complete FP philosophy, detailed pattern explanations, cross-pattern comparisons
|
|
371
|
+
|
|
372
|
+
### Comprehensive Anti-Patterns
|
|
373
|
+
**File**: `anti-patterns.md` (~400 lines)
|
|
374
|
+
**When**: Code review, preventing specific mistakes, team training
|
|
375
|
+
**Contains**: Exhaustive anti-patterns, common mistakes, migration strategies
|
|
376
|
+
|
|
377
|
+
### Testing Methodology
|
|
378
|
+
**File**: `testing-patterns.md` (~500 lines)
|
|
379
|
+
**When**: Building test suites, improving coverage, edge case analysis
|
|
380
|
+
**Contains**: Full testing strategies, edge case patterns, property-based testing
|
|
381
|
+
|
|
382
|
+
### Performance Deep-Dive
|
|
383
|
+
**File**: `performance-patterns.md` (~400 lines)
|
|
384
|
+
**When**: Performance issues identified, optimization needed, benchmarking
|
|
385
|
+
**Contains**: Detailed optimization strategies, profiling techniques, benchmarking patterns
|
|
386
|
+
|
|
387
|
+
### Working Examples
|
|
388
|
+
**Directory**: `examples/`
|
|
389
|
+
**When**: Learning implementation, need working code, integration examples
|
|
390
|
+
**Contains**: Complete working examples with tests
|
|
391
|
+
|
|
392
|
+
## Integration with Domain Skills
|
|
393
|
+
|
|
394
|
+
This core skill provides the foundation for domain-specific skills:
|
|
395
|
+
|
|
396
|
+
- **js-fp-api**: Node.js API patterns with FP principles
|
|
397
|
+
- **js-fp-react**: React component patterns with FP principles
|
|
398
|
+
- **js-fp-vue**: Vue.js component patterns with FP principles
|
|
399
|
+
- **js-fp-wordpress**: WordPress patterns with FP principles
|
|
400
|
+
|
|
401
|
+
Each domain skill references this core and adds domain-specific patterns.
|
|
402
|
+
|
|
403
|
+
## Common Use Cases
|
|
404
|
+
|
|
405
|
+
### Data Validation
|
|
406
|
+
```javascript
|
|
407
|
+
const createValidationRules = (schema) => {
|
|
408
|
+
const rules = schema.map(rule => ({
|
|
409
|
+
field: rule.field,
|
|
410
|
+
validator: compileValidator(rule.type, rule.options),
|
|
411
|
+
message: rule.message
|
|
412
|
+
}))
|
|
413
|
+
|
|
414
|
+
return (data) => {
|
|
415
|
+
const errors = []
|
|
416
|
+
for (const rule of rules) {
|
|
417
|
+
if (!rule.validator(data[rule.field])) {
|
|
418
|
+
errors.push({ field: rule.field, message: rule.message })
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return errors.length === 0 ? { valid: true } : { valid: false, errors }
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### Data Transformation
|
|
427
|
+
```javascript
|
|
428
|
+
// Pipeline without utilities - native chaining
|
|
429
|
+
const processUserData = (rawData) => {
|
|
430
|
+
const normalized = normalizeUserData(rawData)
|
|
431
|
+
if (!normalized.valid) return normalized
|
|
432
|
+
|
|
433
|
+
const validated = validateUserData(normalized.data)
|
|
434
|
+
if (!validated.valid) return validated
|
|
435
|
+
|
|
436
|
+
const enhanced = enhanceWithDefaults(validated.data)
|
|
437
|
+
return { valid: true, data: enhanced }
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
## Success Metrics
|
|
442
|
+
|
|
443
|
+
### Code Quality
|
|
444
|
+
- **Simplicity**: Readable, maintainable code over clever solutions
|
|
445
|
+
- **Testability**: 100% testable pure functions with edge case coverage
|
|
446
|
+
- **Native Integration**: Uses language features effectively
|
|
447
|
+
- **Context-Appropriate**: Matches complexity to actual requirements
|
|
448
|
+
|
|
449
|
+
### Performance (When Needed)
|
|
450
|
+
- **Evidence-Based**: Optimizations backed by measurements
|
|
451
|
+
- **Appropriate Scale**: Simple solutions for small/medium data
|
|
452
|
+
- **Native Optimization**: Leverages language/runtime optimizations
|
|
453
|
+
- **Avoid Over-Engineering**: No complex monitoring for simple apps
|
|
454
|
+
|
|
455
|
+
### Maintainability
|
|
456
|
+
- **Predictable Patterns**: Consistent FP approaches
|
|
457
|
+
- **Easy Testing**: Comprehensive test coverage enabled by purity
|
|
458
|
+
- **Simple Maintenance**: Easy to understand and modify
|
|
459
|
+
- **Documentation**: Clear examples and usage patterns
|
|
460
|
+
|
|
461
|
+
## Philosophy
|
|
462
|
+
|
|
463
|
+
*"Pure functions, native language patterns, appropriate complexity, and comprehensive testing for maintainable, predictable code that respects the language and solves real problems simply."*
|