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.
Files changed (182) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +463 -0
  3. package/dist/cli.js +1064 -0
  4. package/package.json +49 -0
  5. package/platforms/claude/adapter.ts +115 -0
  6. package/platforms/junie/adapter.ts +254 -0
  7. package/platforms/junie/agents-template.md +113 -0
  8. package/platforms/junie/hook-translations.md +84 -0
  9. package/platforms/shared/detector.ts +27 -0
  10. package/platforms/shared/installer.ts +202 -0
  11. package/platforms/shared/types.ts +78 -0
  12. package/plugins/ima-claude/.claude-plugin/plugin.json +25 -0
  13. package/plugins/ima-claude/agents/explorer.md +30 -0
  14. package/plugins/ima-claude/agents/implementer.md +30 -0
  15. package/plugins/ima-claude/agents/memory.md +42 -0
  16. package/plugins/ima-claude/agents/reviewer.md +53 -0
  17. package/plugins/ima-claude/agents/tester.md +33 -0
  18. package/plugins/ima-claude/agents/wp-developer.md +46 -0
  19. package/plugins/ima-claude/hooks/README.md +145 -0
  20. package/plugins/ima-claude/hooks/atlassian_prereqs.py +112 -0
  21. package/plugins/ima-claude/hooks/block_sed_edits.py +59 -0
  22. package/plugins/ima-claude/hooks/bootstrap.sh +90 -0
  23. package/plugins/ima-claude/hooks/bootstrap_utility_check.py +94 -0
  24. package/plugins/ima-claude/hooks/composer_autoload_check.py +70 -0
  25. package/plugins/ima-claude/hooks/docs_organization.py +104 -0
  26. package/plugins/ima-claude/hooks/enforce_rg_over_grep.py +56 -0
  27. package/plugins/ima-claude/hooks/fp_utility_check.py +90 -0
  28. package/plugins/ima-claude/hooks/hook_logger.py +69 -0
  29. package/plugins/ima-claude/hooks/hooks.json +239 -0
  30. package/plugins/ima-claude/hooks/jira_issue_fetch.py +79 -0
  31. package/plugins/ima-claude/hooks/jquery_in_wordpress.py +92 -0
  32. package/plugins/ima-claude/hooks/memory_bootstrap.py +79 -0
  33. package/plugins/ima-claude/hooks/memory_store_reminder.py +75 -0
  34. package/plugins/ima-claude/hooks/prompt_coach.py +125 -0
  35. package/plugins/ima-claude/hooks/prompt_coach_digest.md +48 -0
  36. package/plugins/ima-claude/hooks/prompt_coach_system.md +30 -0
  37. package/plugins/ima-claude/hooks/sequential_thinking_check.py +81 -0
  38. package/plugins/ima-claude/hooks/serena_over_grep.py +96 -0
  39. package/plugins/ima-claude/hooks/serena_over_read.py +66 -0
  40. package/plugins/ima-claude/hooks/serena_project_check.py +133 -0
  41. package/plugins/ima-claude/hooks/sql_injection_check.py +73 -0
  42. package/plugins/ima-claude/hooks/task_master_after_plan.py +31 -0
  43. package/plugins/ima-claude/hooks/task_master_before_impl.py +93 -0
  44. package/plugins/ima-claude/hooks/tavily_extract_advanced.py +48 -0
  45. package/plugins/ima-claude/hooks/vestige_before_external.py +86 -0
  46. package/plugins/ima-claude/hooks/webfetch_to_tavily.py +42 -0
  47. package/plugins/ima-claude/hooks/websearch_to_tavily.py +41 -0
  48. package/plugins/ima-claude/hooks/wp_security_check.py +150 -0
  49. package/plugins/ima-claude/personalities/README.md +45 -0
  50. package/plugins/ima-claude/personalities/enable-40k.md +69 -0
  51. package/plugins/ima-claude/personalities/enable-templars.md +69 -0
  52. package/plugins/ima-claude/skills/.research-summary.md +340 -0
  53. package/plugins/ima-claude/skills/architect/SKILL.md +304 -0
  54. package/plugins/ima-claude/skills/compound-bridge/SKILL.md +200 -0
  55. package/plugins/ima-claude/skills/discourse/SKILL.md +440 -0
  56. package/plugins/ima-claude/skills/discourse-admin/SKILL.md +192 -0
  57. package/plugins/ima-claude/skills/discourse-admin/references/api-endpoints.md +441 -0
  58. package/plugins/ima-claude/skills/discourse-admin/references/gotchas.md +107 -0
  59. package/plugins/ima-claude/skills/discourse-admin/references/staging-defaults.md +98 -0
  60. package/plugins/ima-claude/skills/discourse-admin/scripts/discourse-admin.py +319 -0
  61. package/plugins/ima-claude/skills/docs-organize/SKILL.md +254 -0
  62. package/plugins/ima-claude/skills/docs-organize/templates/active-README.md +50 -0
  63. package/plugins/ima-claude/skills/docs-organize/templates/archive-README.md +57 -0
  64. package/plugins/ima-claude/skills/docs-organize/templates/docs-README.md +43 -0
  65. package/plugins/ima-claude/skills/docs-organize/templates/phase-archive-README.md +83 -0
  66. package/plugins/ima-claude/skills/docs-organize/templates/section-README.md +48 -0
  67. package/plugins/ima-claude/skills/docs-organize/templates/transient-README.md +79 -0
  68. package/plugins/ima-claude/skills/docs-organize/templates/transient-gitignore +9 -0
  69. package/plugins/ima-claude/skills/ember-discourse/SKILL.md +496 -0
  70. package/plugins/ima-claude/skills/functional-programmer/SKILL.md +258 -0
  71. package/plugins/ima-claude/skills/ima-bootstrap/SKILL.md +278 -0
  72. package/plugins/ima-claude/skills/ima-bootstrap/references/bootstrap-patterns.md +356 -0
  73. package/plugins/ima-claude/skills/ima-bootstrap/references/ima-brand.md +273 -0
  74. package/plugins/ima-claude/skills/ima-bootstrap/references/theme-integration.md +212 -0
  75. package/plugins/ima-claude/skills/ima-brand/SKILL.md +108 -0
  76. package/plugins/ima-claude/skills/ima-brand/references/brand-identity.md +140 -0
  77. package/plugins/ima-claude/skills/ima-brand/references/digital-standards.md +180 -0
  78. package/plugins/ima-claude/skills/ima-brand/references/visual-system.md +173 -0
  79. package/plugins/ima-claude/skills/ima-forms-expert/SKILL.md +175 -0
  80. package/plugins/ima-claude/skills/ima-forms-expert/references/container-components.md +154 -0
  81. package/plugins/ima-claude/skills/ima-forms-expert/references/examples.md +328 -0
  82. package/plugins/ima-claude/skills/ima-forms-expert/references/field-components.md +298 -0
  83. package/plugins/ima-claude/skills/ima-forms-expert/references/form-factory.md +193 -0
  84. package/plugins/ima-claude/skills/ima-forms-expert/references/quick-reference.md +153 -0
  85. package/plugins/ima-claude/skills/ima-forms-expert/references/validation-engine.md +336 -0
  86. package/plugins/ima-claude/skills/jira-checkpoint/SKILL.md +178 -0
  87. package/plugins/ima-claude/skills/jquery/SKILL.md +413 -0
  88. package/plugins/ima-claude/skills/js-fp/SKILL.md +463 -0
  89. package/plugins/ima-claude/skills/js-fp/core-principles.md +487 -0
  90. package/plugins/ima-claude/skills/js-fp/examples/pure-functions.js +260 -0
  91. package/plugins/ima-claude/skills/js-fp/examples/tests/pure-functions.test.js +262 -0
  92. package/plugins/ima-claude/skills/js-fp/references/anti-patterns.md +120 -0
  93. package/plugins/ima-claude/skills/js-fp/references/performance-patterns.md +116 -0
  94. package/plugins/ima-claude/skills/js-fp/references/testing-patterns.md +134 -0
  95. package/plugins/ima-claude/skills/js-fp-api/SKILL.md +280 -0
  96. package/plugins/ima-claude/skills/js-fp-api/examples/crud-endpoint.js +258 -0
  97. package/plugins/ima-claude/skills/js-fp-api/references/middleware-patterns.md +134 -0
  98. package/plugins/ima-claude/skills/js-fp-api/references/security-sql.md +110 -0
  99. package/plugins/ima-claude/skills/js-fp-api/references/validation-patterns.md +165 -0
  100. package/plugins/ima-claude/skills/js-fp-react/SKILL.md +447 -0
  101. package/plugins/ima-claude/skills/js-fp-react/examples/ProductCard.tsx +65 -0
  102. package/plugins/ima-claude/skills/js-fp-react/references/hooks-advanced.md +136 -0
  103. package/plugins/ima-claude/skills/js-fp-react/references/performance-patterns.md +175 -0
  104. package/plugins/ima-claude/skills/js-fp-vue/SKILL.md +322 -0
  105. package/plugins/ima-claude/skills/js-fp-vue/references/complete-examples.md +397 -0
  106. package/plugins/ima-claude/skills/js-fp-vue/references/composables-advanced.md +282 -0
  107. package/plugins/ima-claude/skills/js-fp-vue/references/reactivity-patterns.md +348 -0
  108. package/plugins/ima-claude/skills/js-fp-vue/references/testing.md +314 -0
  109. package/plugins/ima-claude/skills/js-fp-wordpress/SKILL.md +301 -0
  110. package/plugins/ima-claude/skills/js-fp-wordpress/references/ajax-patterns.md +192 -0
  111. package/plugins/ima-claude/skills/js-fp-wordpress/references/event-patterns.md +136 -0
  112. package/plugins/ima-claude/skills/js-fp-wordpress/references/wp-integration.md +248 -0
  113. package/plugins/ima-claude/skills/livecanvas/SKILL.md +209 -0
  114. package/plugins/ima-claude/skills/livecanvas/references/livecanvas-features.md +311 -0
  115. package/plugins/ima-claude/skills/livecanvas/references/loops-and-logic.md +730 -0
  116. package/plugins/ima-claude/skills/livecanvas/references/picostrap.md +227 -0
  117. package/plugins/ima-claude/skills/mcp-atlassian/SKILL.md +339 -0
  118. package/plugins/ima-claude/skills/mcp-context7/SKILL.md +109 -0
  119. package/plugins/ima-claude/skills/mcp-memory/SKILL.md +182 -0
  120. package/plugins/ima-claude/skills/mcp-qdrant/SKILL.md +233 -0
  121. package/plugins/ima-claude/skills/mcp-sequential/SKILL.md +149 -0
  122. package/plugins/ima-claude/skills/mcp-serena/SKILL.md +174 -0
  123. package/plugins/ima-claude/skills/mcp-tavily/SKILL.md +118 -0
  124. package/plugins/ima-claude/skills/mcp-vestige/SKILL.md +259 -0
  125. package/plugins/ima-claude/skills/php-authnet/SKILL.md +275 -0
  126. package/plugins/ima-claude/skills/php-authnet/references/api-reference.md +624 -0
  127. package/plugins/ima-claude/skills/php-authnet/references/sandbox-testing.md +424 -0
  128. package/plugins/ima-claude/skills/php-fp/SKILL.md +333 -0
  129. package/plugins/ima-claude/skills/php-fp/examples/pure-functions.php +403 -0
  130. package/plugins/ima-claude/skills/php-fp/examples/tests/PureFunctionsTest.php +515 -0
  131. package/plugins/ima-claude/skills/php-fp/references/core-principles.md +277 -0
  132. package/plugins/ima-claude/skills/php-fp/references/testing-patterns.md +374 -0
  133. package/plugins/ima-claude/skills/php-fp-wordpress/SKILL.md +216 -0
  134. package/plugins/ima-claude/skills/php-fp-wordpress/references/fp-patterns.md +275 -0
  135. package/plugins/ima-claude/skills/php-fp-wordpress/references/plugin-architecture.md +295 -0
  136. package/plugins/ima-claude/skills/php-fp-wordpress/references/security-examples.md +203 -0
  137. package/plugins/ima-claude/skills/php-fp-wordpress/references/testing-strategy.md +259 -0
  138. package/plugins/ima-claude/skills/phpunit-wp/SKILL.md +716 -0
  139. package/plugins/ima-claude/skills/playwright/SKILL.md +434 -0
  140. package/plugins/ima-claude/skills/playwright/references/accessibility-testing.md +153 -0
  141. package/plugins/ima-claude/skills/playwright/references/ci-cd.md +268 -0
  142. package/plugins/ima-claude/skills/playwright/references/network-mocking.md +270 -0
  143. package/plugins/ima-claude/skills/playwright/references/visual-regression.md +215 -0
  144. package/plugins/ima-claude/skills/py-fp/SKILL.md +663 -0
  145. package/plugins/ima-claude/skills/py-fp/examples/pure-functions.py +185 -0
  146. package/plugins/ima-claude/skills/py-fp/examples/tests/test_pure_functions.py +244 -0
  147. package/plugins/ima-claude/skills/py-fp/references/core-principles.md +381 -0
  148. package/plugins/ima-claude/skills/py-fp/references/testing-patterns.md +283 -0
  149. package/plugins/ima-claude/skills/quasar-fp/SKILL.md +327 -0
  150. package/plugins/ima-claude/skills/quasar-fp/metadata.json +85 -0
  151. package/plugins/ima-claude/skills/quasar-fp/references/component-patterns.md +257 -0
  152. package/plugins/ima-claude/skills/quasar-fp/references/theme-integration.md +233 -0
  153. package/plugins/ima-claude/skills/quasar-fp/references/utility-classes.md +237 -0
  154. package/plugins/ima-claude/skills/quickstart/SKILL.md +129 -0
  155. package/plugins/ima-claude/skills/rails/SKILL.md +359 -0
  156. package/plugins/ima-claude/skills/resume-session/SKILL.md +68 -0
  157. package/plugins/ima-claude/skills/rg/SKILL.md +205 -0
  158. package/plugins/ima-claude/skills/ruby-fp/SKILL.md +336 -0
  159. package/plugins/ima-claude/skills/save-session/SKILL.md +81 -0
  160. package/plugins/ima-claude/skills/scorecard/SKILL.md +96 -0
  161. package/plugins/ima-claude/skills/skill-analyzer/SKILL.md +127 -0
  162. package/plugins/ima-claude/skills/skill-analyzer/references/advanced-checklist.md +44 -0
  163. package/plugins/ima-claude/skills/skill-analyzer/references/core-checklist.md +60 -0
  164. package/plugins/ima-claude/skills/skill-analyzer/scripts/analyze_skill.py +418 -0
  165. package/plugins/ima-claude/skills/skill-creator/LICENSE.txt +202 -0
  166. package/plugins/ima-claude/skills/skill-creator/SKILL.md +343 -0
  167. package/plugins/ima-claude/skills/skill-creator/references/output-patterns.md +82 -0
  168. package/plugins/ima-claude/skills/skill-creator/references/workflows.md +28 -0
  169. package/plugins/ima-claude/skills/skill-creator/scripts/init_skill.py +303 -0
  170. package/plugins/ima-claude/skills/skill-creator/scripts/package_skill.py +110 -0
  171. package/plugins/ima-claude/skills/skill-creator/scripts/quick_validate.py +103 -0
  172. package/plugins/ima-claude/skills/task-master/SKILL.md +51 -0
  173. package/plugins/ima-claude/skills/task-planner/SKILL.md +228 -0
  174. package/plugins/ima-claude/skills/task-runner/SKILL.md +192 -0
  175. package/plugins/ima-claude/skills/unit-testing/SKILL.md +198 -0
  176. package/plugins/ima-claude/skills/unit-testing/references/mock-patterns.md +181 -0
  177. package/plugins/ima-claude/skills/unit-testing/references/tdd-workflow.md +177 -0
  178. package/plugins/ima-claude/skills/unit-testing/references/test-strategy.md +126 -0
  179. package/plugins/ima-claude/skills/wp-local/SKILL.md +246 -0
  180. package/plugins/ima-claude/skills/wp-local/references/configuration.md +198 -0
  181. package/plugins/ima-claude/skills/wp-local/references/wp-cli-reference.md +406 -0
  182. package/plugins/ima-claude/skills/wp-local/scripts/wp-local.sh +61 -0
@@ -0,0 +1,116 @@
1
+ # Performance Patterns Reference
2
+
3
+ Evidence-based optimization through pure functions.
4
+
5
+ ## Core Formula
6
+
7
+ ```
8
+ Pure Function + Closure + Pre-compilation = Exceptional Performance
9
+ ```
10
+
11
+ ## The Pre-Compilation Pattern
12
+
13
+ **Problem**: O(records x fields) - configuration accessed every iteration
14
+
15
+ ```javascript
16
+ // SLOW: 100,000 records x 24 fields = 2.4 million iterations
17
+ function processRecords(records, schema) {
18
+ return records.map(record => {
19
+ return schema.fields.reduce((obj, field) => {
20
+ obj[field.name] = transformField(record[field.name], field.type)
21
+ return obj
22
+ }, {})
23
+ })
24
+ }
25
+ ```
26
+
27
+ **Solution**: Pre-compile configuration into closures
28
+
29
+ ```javascript
30
+ // FAST: O(records + fields) - configuration extracted once
31
+ export const mapRecord = ({prefix, fields}) => {
32
+ const allowedFields = Object.keys(fields)
33
+
34
+ // Return optimized mapping function
35
+ return (record) => {
36
+ const map = {}
37
+ allowedFields.forEach((key) => {
38
+ const val = record[prefix + '_' + key]
39
+ map[key] = fields[key].formatter ? fields[key].formatter(val) : val
40
+ })
41
+ return map
42
+ }
43
+ }
44
+
45
+ // Usage
46
+ const mapper = mapRecord(meta) // Configure once
47
+ const objects = records.map(mapper) // Linear performance
48
+ ```
49
+
50
+ **Result**: 10-25x improvement on large datasets
51
+
52
+ ## Function Factory Pattern
53
+
54
+ ```javascript
55
+ // Create specialized functions - configuration cost paid once
56
+ const createValidator = (rules) => (value) => {
57
+ const errors = []
58
+ for (const rule of rules) {
59
+ if (!rule.validator(value)) {
60
+ errors.push(rule.message)
61
+ }
62
+ }
63
+ return errors.length === 0 ? { valid: true } : { valid: false, errors }
64
+ }
65
+
66
+ // Configure once
67
+ const validateEmail = createValidator([
68
+ { validator: v => typeof v === 'string', message: 'Must be string' },
69
+ { validator: v => v.includes('@'), message: 'Must contain @' }
70
+ ])
71
+
72
+ // Use many times (fast)
73
+ emails.map(validateEmail)
74
+ ```
75
+
76
+ ## Triple-Layer Curry Pattern
77
+
78
+ ```
79
+ (Configuration) => (Parameters) => (Context) => Result
80
+ ```
81
+
82
+ ```javascript
83
+ export const selectUserByEmail = (meta) => (user) => async (ctx) => {
84
+ const sql = getSelectStmt(meta)({whereSet: [{field: 'email'}]})
85
+ const results = await ctx.db.query({sql, values: [user.email]})
86
+ return mapRecord(meta)(results[0])
87
+ }
88
+
89
+ // Layer 1: Configuration (compile-time)
90
+ const configuredQuery = selectUserByEmail(initMeta(userMeta))
91
+
92
+ // Layers 2+3: Runtime execution
93
+ const user = await configuredQuery({email: 'test@example.com'})(context)
94
+ ```
95
+
96
+ ## When to Optimize
97
+
98
+ 1. **Measure first** - Profile before optimizing
99
+ 2. **>10K items** - Pre-compilation matters at scale
100
+ 3. **Repeated config access** - Look for nested loops accessing setup data
101
+ 4. **Hot paths** - Focus on frequently called code
102
+
103
+ ## When NOT to Optimize
104
+
105
+ - Small datasets (<1K items)
106
+ - One-time operations
107
+ - Code readability suffers significantly
108
+ - No measured performance problem
109
+
110
+ ## Quick Optimization Checklist
111
+
112
+ 1. [ ] Identify repeated configuration access in loops
113
+ 2. [ ] Extract configuration phase outside execution loop
114
+ 3. [ ] Use closures to cache configuration
115
+ 4. [ ] Verify linear execution (not quadratic)
116
+ 5. [ ] Benchmark before/after with real data
@@ -0,0 +1,134 @@
1
+ # Testing Patterns Reference
2
+
3
+ Comprehensive edge-case testing enabled by pure functions.
4
+
5
+ ## Core Principle
6
+
7
+ Test systematically against ALL data types and edge cases. Pure functions make this practical:
8
+ - Same input always produces same output
9
+ - No side effects - tests don't interfere
10
+ - Fast execution - pure functions run quickly
11
+ - Predictable behavior - easy to reason about
12
+
13
+ ## Test Matrix Template
14
+
15
+ ```javascript
16
+ describe('FunctionUnderTest', () => {
17
+ describe('valid inputs', () => {
18
+ it('should handle expected use cases', () => {
19
+ expect(validateIntegerGreaterThan(0)(5)).toBe(true)
20
+ expect(validateIntegerGreaterThan(0)('5')).toBe(true) // String numbers
21
+ })
22
+ })
23
+
24
+ describe('invalid types', () => {
25
+ // Test against ALL JavaScript types
26
+ it('should reject null', () => expect(fn(null)).toBe(false))
27
+ it('should reject undefined', () => expect(fn(undefined)).toBe(false))
28
+ it('should reject NaN', () => expect(fn(NaN)).toBe(false))
29
+ it('should reject boolean', () => expect(fn(true)).toBe(false))
30
+ it('should reject array', () => expect(fn([])).toBe(false))
31
+ it('should reject object', () => expect(fn({})).toBe(false))
32
+ it('should reject function', () => expect(fn(() => {})).toBe(false))
33
+ })
34
+
35
+ describe('edge cases', () => {
36
+ // Boundary values, empty inputs, extreme values
37
+ })
38
+
39
+ describe('composition', () => {
40
+ // Test function combinations
41
+ })
42
+ })
43
+ ```
44
+
45
+ ## Parameterized Test Pattern
46
+
47
+ ```javascript
48
+ describe('calculateDiscount', () => {
49
+ describe('valid inputs', () => {
50
+ const testCases = [
51
+ [100, 0.1, 10],
52
+ [50, 0.2, 10],
53
+ [0, 0.1, 0]
54
+ ]
55
+
56
+ testCases.forEach(([price, rate, expected]) => {
57
+ it(`${rate*100}% discount on ${price} = ${expected}`, () => {
58
+ expect(calculateDiscount(price, rate)).toBe(expected)
59
+ })
60
+ })
61
+ })
62
+
63
+ describe('invalid types', () => {
64
+ const invalidTypes = [null, undefined, NaN, true, [], {}, '100']
65
+
66
+ invalidTypes.forEach(input => {
67
+ it(`handles ${typeof input} (${String(input)}) gracefully`, () => {
68
+ expect(() => calculateDiscount(input, 0.1)).not.toThrow()
69
+ expect(calculateDiscount(input, 0.1)).toBe(0)
70
+ })
71
+ })
72
+ })
73
+ })
74
+ ```
75
+
76
+ ## Testing Composed Functions
77
+
78
+ ```javascript
79
+ describe('validateCreditCard', () => {
80
+ const validCard = {
81
+ name: 'John Doe',
82
+ number: '4111111111111111',
83
+ expDate: '12/26',
84
+ cvv: '123'
85
+ }
86
+
87
+ it('accepts valid complete card', () => {
88
+ expect(validateCreditCard(validCard)).toEqual({ valid: true })
89
+ })
90
+
91
+ // Test each field independently
92
+ const fields = ['name', 'number', 'expDate', 'cvv']
93
+ fields.forEach(field => {
94
+ it(`rejects missing ${field}`, () => {
95
+ const invalid = { ...validCard, [field]: '' }
96
+ expect(validateCreditCard(invalid).valid).toBe(false)
97
+ })
98
+ })
99
+ })
100
+ ```
101
+
102
+ ## Testing Pure Functions with Dependencies
103
+
104
+ ```javascript
105
+ // Function under test
106
+ const saveUser = async (userData, hasher, database) => {
107
+ const hashedPassword = await hasher.hash(userData.password)
108
+ return database.save({ ...userData, password: hashedPassword })
109
+ }
110
+
111
+ // Test with mock dependencies
112
+ describe('saveUser', () => {
113
+ const mockHasher = { hash: jest.fn(p => `hashed_${p}`) }
114
+ const mockDb = { save: jest.fn(user => ({ id: 1, ...user })) }
115
+
116
+ it('hashes password and saves user', async () => {
117
+ const result = await saveUser(
118
+ { email: 'test@example.com', password: 'secret' },
119
+ mockHasher,
120
+ mockDb
121
+ )
122
+ expect(mockHasher.hash).toHaveBeenCalledWith('secret')
123
+ expect(result.password).toBe('hashed_secret')
124
+ })
125
+ })
126
+ ```
127
+
128
+ ## Quick Checklist
129
+
130
+ - [ ] Test all JavaScript types (null, undefined, NaN, boolean, array, object, function)
131
+ - [ ] Test boundary values (0, -1, MAX_SAFE_INTEGER, empty string, empty array)
132
+ - [ ] Test composition of functions together
133
+ - [ ] Mock dependencies for isolation
134
+ - [ ] Use parameterized tests for data variations
@@ -0,0 +1,280 @@
1
+ ---
2
+ name: "js-fp-api"
3
+ description: "FP API patterns for Node.js with security-first SQL and middleware DI - references js-fp core"
4
+ ---
5
+
6
+ # JavaScript FP - Node.js API
7
+
8
+ Functional programming patterns for Node.js APIs with security-first SQL, middleware dependency injection, and self-contained routes.
9
+
10
+ ## When to Use This Skill
11
+
12
+ - Building REST APIs with Node.js
13
+ - Need security-first SQL patterns
14
+ - Implementing middleware-based dependency injection
15
+ - Self-contained route architecture
16
+ - Testing API endpoints comprehensively
17
+
18
+ ## Core Philosophy
19
+
20
+ **Self-contained routes** (300-500 lines max) with **security-first SQL**, **middleware DI**, and **pure business logic separation** when genuinely reusable (3+ routes).
21
+
22
+ **Foundation**: This skill builds on `js-fp` core principles. Reference `../js-fp/SKILL.md` for purity, composition, dependency injection, and testing patterns.
23
+
24
+ ## CRITICAL: Security-First SQL (MANDATORY)
25
+
26
+ **Rule**: NEVER use string concatenation for SQL. ALWAYS use parameterized queries.
27
+
28
+ ```javascript
29
+ // NEVER: SQL injection vulnerability
30
+ const sql = `SELECT * FROM events WHERE domain LIKE '%${domain}%'` // DANGER!
31
+
32
+ // ALWAYS: Parameterized queries returning {sql, params}
33
+ const buildDomainFilter = (domain) => {
34
+ const validation = validateDomain(domain)
35
+ if (!validation.valid) throw new Error(validation.error)
36
+ if (validation.domain === 'all') return { sql: '', params: {} }
37
+
38
+ return {
39
+ sql: 'AND from_address LIKE @domain_pattern',
40
+ params: { domain_pattern: `%${validation.domain}%` }
41
+ }
42
+ }
43
+ ```
44
+
45
+ **Deep Dive**: See `references/security-sql.md` for advanced SQL patterns, triple-layer curry, and domain whitelisting.
46
+
47
+ ## Mandatory Architecture
48
+
49
+ ### File Structure
50
+
51
+ ```
52
+ /api/
53
+ ├── middleware/ # DI only (database.js, auth.js)
54
+ ├── shared/ # ONLY if 3+ routes use it
55
+ │ ├── validators.js # Domain whitelisting, validation
56
+ │ ├── filters.js # SQL builders returning {sql, params}
57
+ │ └── constants.js # Static config
58
+ ├── business/ # Pure functions ONLY (calculations, transformations)
59
+ └── routes/
60
+ ├── [domain]/ # Logical grouping
61
+ │ ├── index.js # Route orchestrator
62
+ │ └── [endpoint].js # 300-500 lines MAX
63
+ └── [simple].js # Standalone endpoints
64
+ ```
65
+
66
+ ### Self-Contained Route Pattern (ENFORCE)
67
+
68
+ ```javascript
69
+ import { Hono } from 'hono'
70
+ import { validateDomain } from '../../shared/validators.js'
71
+ import { buildDomainFilter } from '../../shared/filters.js'
72
+
73
+ const route = new Hono()
74
+
75
+ // ───── Route-scoped validation ─────
76
+ const validateRequest = (ctx) => {
77
+ const domain = ctx.req.query('domain')
78
+ const validation = validateDomain(domain)
79
+ if (!validation.valid) {
80
+ const error = new Error(validation.error)
81
+ error.status = 400
82
+ throw error
83
+ }
84
+ return { domain: validation.domain }
85
+ }
86
+
87
+ // ───── Security-first SQL building ─────
88
+ const buildQuery = (env, { domain }) => {
89
+ const table = getTableReference(env)('events')
90
+ const filters = buildDomainFilter(domain)
91
+
92
+ return {
93
+ sql: `SELECT * FROM ${table} WHERE 1=1 ${filters.sql}`,
94
+ params: filters.params
95
+ }
96
+ }
97
+
98
+ // ───── Business logic (keep in-route if <50 lines) ─────
99
+ const processData = (raw) => raw.map(r => ({
100
+ ...r,
101
+ timestamp: r.timestamp + 'Z'
102
+ }))
103
+
104
+ // ───── Clean orchestration ─────
105
+ route.get('/', async (c) => {
106
+ try {
107
+ const params = validateRequest(c)
108
+ const { sql, params: qp } = buildQuery(c.env, params)
109
+ const raw = await c.db.queryWithParams(sql, qp) // Middleware-injected
110
+ return c.json({ success: true, data: processData(raw) })
111
+ } catch (error) {
112
+ return c.json({ success: false, error: error.message }, error.status || 500)
113
+ }
114
+ })
115
+
116
+ export default route
117
+ ```
118
+
119
+ ## Middleware Dependency Injection
120
+
121
+ Inject dependencies via middleware context, not per-request instantiation.
122
+
123
+ ```javascript
124
+ // middleware/database.js
125
+ export const databaseMiddleware = async (c, next) => {
126
+ const db = createDatabaseClient(c.env.DATABASE_URL)
127
+ c.db = {
128
+ query: (sql) => db.query(sql),
129
+ queryWithParams: (sql, params) => db.query(sql, params),
130
+ transaction: (fn) => db.transaction(fn)
131
+ }
132
+ await next()
133
+ }
134
+
135
+ // Usage in routes: await c.db.queryWithParams(sql, params)
136
+ ```
137
+
138
+ **Deep Dive**: See `references/middleware-patterns.md` for function factories, auth middleware, and testing patterns.
139
+
140
+ ## When to Extract to business/
141
+
142
+ **Extract ONLY if**:
143
+ - Function is genuinely reusable (3+ routes use it)
144
+ - Pure calculation/transformation
145
+ - No side effects
146
+ - 100% testable
147
+
148
+ ```javascript
149
+ // business/calculations.js
150
+ export const calculateTotalRevenue = (orders) =>
151
+ orders.reduce((sum, order) => sum + order.total, 0)
152
+
153
+ export const calculateAverageOrderValue = (orders) => {
154
+ if (orders.length === 0) return 0
155
+ return calculateTotalRevenue(orders) / orders.length
156
+ }
157
+ ```
158
+
159
+ ## Anti-Patterns (REJECT)
160
+
161
+ ```javascript
162
+ // Routes >500 lines → Split to business/
163
+ // Service layer files → Keep in-route or business/
164
+ // String concatenation SQL → Use {sql, params}
165
+ // Manual client init → Use middleware DI
166
+ // Validation files used by <3 routes → Keep in-route
167
+ // Abstraction layers → Direct implementation
168
+ // Complex error handling frameworks → Simple try/catch
169
+ // Over-engineered logging → Simple logger DI
170
+ ```
171
+
172
+ ## Testing Strategy
173
+
174
+ ### Pure Business Logic Tests
175
+
176
+ ```javascript
177
+ import { calculateTotalRevenue } from '../calculations.js'
178
+
179
+ describe('calculateTotalRevenue', () => {
180
+ it('sums order totals', () => {
181
+ const orders = [{ total: 100 }, { total: 200 }, { total: 50 }]
182
+ expect(calculateTotalRevenue(orders)).toBe(350)
183
+ })
184
+
185
+ it('handles empty array', () => {
186
+ expect(calculateTotalRevenue([])).toBe(0)
187
+ })
188
+ })
189
+ ```
190
+
191
+ ### Route Integration Tests
192
+
193
+ ```javascript
194
+ describe('GET /orders', () => {
195
+ const mockDb = {
196
+ queryWithParams: jest.fn().mockResolvedValue([{ id: 1, total: 100 }])
197
+ }
198
+
199
+ it('returns orders successfully', async () => {
200
+ const res = await app.request('/orders', { method: 'GET' }, { db: mockDb })
201
+ expect(res.status).toBe(200)
202
+ })
203
+
204
+ it('validates required parameters', async () => {
205
+ const res = await app.request('/orders?domain=invalid', { method: 'GET' }, { db: mockDb })
206
+ expect(res.status).toBe(400)
207
+ })
208
+ })
209
+ ```
210
+
211
+ **Deep Dive**: See `references/middleware-patterns.md` for comprehensive testing patterns.
212
+
213
+ ## Quality Gates
214
+
215
+ Before implementing any API endpoint:
216
+
217
+ 1. **Security-first SQL**: Using `{sql, params}` pattern?
218
+ 2. **Route size**: Can route be <500 lines?
219
+ 3. **Validation**: Route-scoped closures or shared (3+ routes)?
220
+ 4. **Middleware DI**: Using `c.db`, `c.bq`, `c.logger`?
221
+ 5. **Pure business logic**: Extracted if reusable (3+ routes)?
222
+ 6. **Testing**: Can inject mocks for all dependencies?
223
+ 7. **FP principles**: Pure functions, explicit dependencies?
224
+
225
+ ## When to Load Reference Files
226
+
227
+ ### Security Deep-Dive
228
+ **File**: `references/security-sql.md`
229
+ **Load When**:
230
+ - Building complex multi-filter queries
231
+ - Implementing triple-layer curry pattern
232
+ - Training team on SQL security
233
+ - Debugging injection vulnerabilities
234
+ **Contains**: Parameterized queries, SQL builders, domain whitelisting, security checklist
235
+
236
+ ### Middleware Patterns
237
+ **File**: `references/middleware-patterns.md`
238
+ **Load When**:
239
+ - Building custom middleware
240
+ - Implementing function factories for O(1) performance
241
+ - Setting up auth middleware
242
+ - Writing comprehensive integration tests
243
+ **Contains**: Context-based DI, function factories, auth patterns, testing with mocks
244
+
245
+ ### Validation Strategies
246
+ **File**: `references/validation-patterns.md`
247
+ **Load When**:
248
+ - Implementing complex validation logic
249
+ - Building composable validators
250
+ - Deciding where to place validation code
251
+ - Implementing error accumulation
252
+ **Contains**: validateAll utility, composition patterns, result objects, when to extract
253
+
254
+ ### Working Examples
255
+ **Directory**: `examples/`
256
+ **Load When**: Need complete working API examples
257
+ **Contains**: Full CRUD endpoints, authentication, authorization, testing
258
+
259
+ ## Foundation Reference
260
+
261
+ **Core FP Principles**: `../js-fp/SKILL.md`
262
+ - Purity and side effect isolation
263
+ - Composition patterns
264
+ - Dependency injection
265
+ - Immutability
266
+ - Testing strategies
267
+
268
+ **Deep Dive**: `../js-fp/core-principles.md` for complete FP philosophy
269
+
270
+ ## Success Metrics
271
+
272
+ - **Security**: Zero SQL injection vulnerabilities
273
+ - **Testability**: 95%+ coverage for pure functions
274
+ - **Maintainability**: Routes under 500 lines
275
+ - **Performance**: Sub-200ms response times
276
+ - **Code Quality**: Clear, self-documenting code
277
+
278
+ ## Philosophy
279
+
280
+ *"Self-contained routes with security-first SQL and minimal abstraction - optimize for readability and security over clever architecture."*