awesome-slash 2.4.2
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/.claude-plugin/marketplace.json +54 -0
- package/.claude-plugin/plugin.json +11 -0
- package/.mcp.json +8 -0
- package/CHANGELOG.md +261 -0
- package/LICENSE +21 -0
- package/README.md +363 -0
- package/SECURITY.md +101 -0
- package/adapters/README.md +256 -0
- package/adapters/codex/README.md +272 -0
- package/adapters/codex/install.sh +179 -0
- package/adapters/opencode/README.md +301 -0
- package/adapters/opencode/install.sh +223 -0
- package/lib/patterns/review-patterns.js +511 -0
- package/lib/patterns/slop-patterns.js +647 -0
- package/lib/platform/detect-platform.js +535 -0
- package/lib/platform/verify-tools.js +235 -0
- package/lib/state/workflow-state.js +635 -0
- package/lib/state/workflow-state.schema.json +282 -0
- package/lib/utils/context-optimizer.js +227 -0
- package/mcp-server/index.js +303 -0
- package/mcp-server/package.json +23 -0
- package/package.json +63 -0
- package/plugins/deslop-around/.claude-plugin/plugin.json +20 -0
- package/plugins/deslop-around/commands/deslop-around.md +220 -0
- package/plugins/deslop-around/lib/patterns/review-patterns.js +511 -0
- package/plugins/deslop-around/lib/patterns/slop-patterns.js +641 -0
- package/plugins/deslop-around/lib/platform/detect-platform.js +514 -0
- package/plugins/deslop-around/lib/platform/verify-tools.js +235 -0
- package/plugins/deslop-around/lib/state/workflow-state.js +635 -0
- package/plugins/deslop-around/lib/state/workflow-state.schema.json +282 -0
- package/plugins/deslop-around/lib/utils/context-optimizer.js +222 -0
- package/plugins/next-task/.claude-plugin/plugin.json +24 -0
- package/plugins/next-task/agents/ci-fixer.md +236 -0
- package/plugins/next-task/agents/ci-monitor.md +291 -0
- package/plugins/next-task/agents/delivery-validator.md +451 -0
- package/plugins/next-task/agents/deslop-work.md +272 -0
- package/plugins/next-task/agents/docs-updater.md +506 -0
- package/plugins/next-task/agents/exploration-agent.md +277 -0
- package/plugins/next-task/agents/implementation-agent.md +427 -0
- package/plugins/next-task/agents/planning-agent.md +236 -0
- package/plugins/next-task/agents/policy-selector.md +248 -0
- package/plugins/next-task/agents/review-orchestrator.md +521 -0
- package/plugins/next-task/agents/simple-fixer.md +136 -0
- package/plugins/next-task/agents/task-discoverer.md +357 -0
- package/plugins/next-task/agents/test-coverage-checker.md +447 -0
- package/plugins/next-task/agents/worktree-manager.md +419 -0
- package/plugins/next-task/commands/delivery-approval.md +331 -0
- package/plugins/next-task/commands/next-task.md +627 -0
- package/plugins/next-task/commands/update-docs-around.md +418 -0
- package/plugins/next-task/hooks/hooks.json +14 -0
- package/plugins/next-task/lib/patterns/review-patterns.js +511 -0
- package/plugins/next-task/lib/patterns/slop-patterns.js +641 -0
- package/plugins/next-task/lib/platform/detect-platform.js +514 -0
- package/plugins/next-task/lib/platform/verify-tools.js +235 -0
- package/plugins/next-task/lib/state/tasks-registry.schema.json +85 -0
- package/plugins/next-task/lib/state/workflow-state.js +635 -0
- package/plugins/next-task/lib/state/workflow-state.schema.json +282 -0
- package/plugins/next-task/lib/state/worktree-status.schema.json +219 -0
- package/plugins/next-task/lib/utils/context-optimizer.js +222 -0
- package/plugins/project-review/.claude-plugin/plugin.json +20 -0
- package/plugins/project-review/commands/project-review-agents.md +286 -0
- package/plugins/project-review/commands/project-review-github.md +142 -0
- package/plugins/project-review/commands/project-review.md +273 -0
- package/plugins/project-review/lib/patterns/review-patterns.js +511 -0
- package/plugins/project-review/lib/patterns/slop-patterns.js +641 -0
- package/plugins/project-review/lib/platform/detect-platform.js +514 -0
- package/plugins/project-review/lib/platform/verify-tools.js +235 -0
- package/plugins/project-review/lib/state/workflow-state.js +635 -0
- package/plugins/project-review/lib/state/workflow-state.schema.json +282 -0
- package/plugins/project-review/lib/utils/context-optimizer.js +222 -0
- package/plugins/reality-check/.claude-plugin/plugin.json +23 -0
- package/plugins/reality-check/README.md +156 -0
- package/plugins/reality-check/agents/code-explorer.md +353 -0
- package/plugins/reality-check/agents/doc-analyzer.md +337 -0
- package/plugins/reality-check/agents/issue-scanner.md +231 -0
- package/plugins/reality-check/agents/plan-synthesizer.md +479 -0
- package/plugins/reality-check/commands/scan.md +242 -0
- package/plugins/reality-check/commands/set.md +203 -0
- package/plugins/reality-check/lib/state/reality-check-state.js +509 -0
- package/plugins/reality-check/skills/reality-analysis/SKILL.md +317 -0
- package/plugins/ship/.claude-plugin/plugin.json +21 -0
- package/plugins/ship/commands/ship-ci-review-loop.md +443 -0
- package/plugins/ship/commands/ship-deployment.md +330 -0
- package/plugins/ship/commands/ship-error-handling.md +254 -0
- package/plugins/ship/commands/ship.md +370 -0
- package/plugins/ship/lib/patterns/review-patterns.js +511 -0
- package/plugins/ship/lib/patterns/slop-patterns.js +641 -0
- package/plugins/ship/lib/platform/detect-platform.js +514 -0
- package/plugins/ship/lib/platform/verify-tools.js +235 -0
- package/plugins/ship/lib/state/workflow-state.js +635 -0
- package/plugins/ship/lib/state/workflow-state.schema.json +282 -0
- package/plugins/ship/lib/utils/context-optimizer.js +222 -0
- package/scripts/install/claude.sh +50 -0
- package/scripts/install/codex.sh +181 -0
- package/scripts/install/opencode.sh +211 -0
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Review Patterns Library
|
|
3
|
+
* Framework-specific code review patterns for intelligent code review
|
|
4
|
+
*
|
|
5
|
+
* These patterns guide AI agents to look for tech-stack-specific issues
|
|
6
|
+
*
|
|
7
|
+
* @author Avi Fenesh
|
|
8
|
+
* @license MIT
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Deep freeze an object for V8 optimization and immutability
|
|
13
|
+
* @param {Object} obj - Object to freeze
|
|
14
|
+
* @returns {Object} Frozen object
|
|
15
|
+
*/
|
|
16
|
+
function deepFreeze(obj) {
|
|
17
|
+
Object.keys(obj).forEach(key => {
|
|
18
|
+
if (typeof obj[key] === 'object' && obj[key] !== null && !(obj[key] instanceof RegExp)) {
|
|
19
|
+
deepFreeze(obj[key]);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
return Object.freeze(obj);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const reviewPatterns = {
|
|
26
|
+
/**
|
|
27
|
+
* React framework patterns
|
|
28
|
+
*/
|
|
29
|
+
react: {
|
|
30
|
+
hooks_rules: [
|
|
31
|
+
'useEffect with missing dependencies in dependency array',
|
|
32
|
+
'useState called inside loops or conditionally',
|
|
33
|
+
'Hooks called conditionally (violates Rules of Hooks)',
|
|
34
|
+
'useCallback without proper dependency array',
|
|
35
|
+
'useMemo overused on cheap calculations',
|
|
36
|
+
'useEffect cleanup function missing for subscriptions',
|
|
37
|
+
'Stale closure bugs in useEffect/useCallback'
|
|
38
|
+
],
|
|
39
|
+
state_management: [
|
|
40
|
+
'Prop drilling deeper than 3 levels (consider Context)',
|
|
41
|
+
'Redundant state that can be derived from props',
|
|
42
|
+
'State updates not using functional form when depending on previous state',
|
|
43
|
+
'Too many useState hooks (consider useReducer)',
|
|
44
|
+
'State lifted too high in component tree',
|
|
45
|
+
'Missing key prop in list rendering',
|
|
46
|
+
'Mutating state directly instead of using setState'
|
|
47
|
+
],
|
|
48
|
+
performance: [
|
|
49
|
+
'Missing React.memo on expensive components',
|
|
50
|
+
'Inline function/object props causing unnecessary re-renders',
|
|
51
|
+
'Large objects/arrays in Context causing frequent re-renders',
|
|
52
|
+
'Expensive calculations not wrapped in useMemo',
|
|
53
|
+
'Component re-rendering too frequently (check React DevTools)',
|
|
54
|
+
'Bundle size issues from importing entire libraries',
|
|
55
|
+
'Lazy loading not used for code splitting'
|
|
56
|
+
],
|
|
57
|
+
common_mistakes: [
|
|
58
|
+
'Comparing objects/arrays in useEffect dependencies',
|
|
59
|
+
'Using index as key in dynamic lists',
|
|
60
|
+
'Conditional rendering with && that shows 0 instead of nothing',
|
|
61
|
+
'Not handling loading and error states',
|
|
62
|
+
'Forgetting to cleanup effects (memory leaks)',
|
|
63
|
+
'Using findDOMNode or string refs (deprecated)'
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Vue.js framework patterns
|
|
69
|
+
*/
|
|
70
|
+
vue: {
|
|
71
|
+
reactivity: [
|
|
72
|
+
'Mutating props directly instead of emitting events',
|
|
73
|
+
'Not using computed properties for derived state',
|
|
74
|
+
'Reactive data not declared in data() function',
|
|
75
|
+
'Using wrong reactivity API (Vue 2 vs Vue 3)',
|
|
76
|
+
'Missing deep watchers when needed',
|
|
77
|
+
'Overusing watchers instead of computed properties'
|
|
78
|
+
],
|
|
79
|
+
composition_api: [
|
|
80
|
+
'Ref vs reactive usage inconsistencies',
|
|
81
|
+
'Forgetting .value when accessing refs',
|
|
82
|
+
'Creating refs/reactive objects outside setup()',
|
|
83
|
+
'Not destructuring reactive objects properly',
|
|
84
|
+
'Missing proper TypeScript types for refs'
|
|
85
|
+
],
|
|
86
|
+
performance: [
|
|
87
|
+
'v-for without proper key binding',
|
|
88
|
+
'Using v-for and v-if on same element',
|
|
89
|
+
'Not using v-once for static content',
|
|
90
|
+
'Missing keep-alive for cached components',
|
|
91
|
+
'Watchers running on every keystroke without debounce'
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Angular framework patterns
|
|
97
|
+
*/
|
|
98
|
+
angular: {
|
|
99
|
+
change_detection: [
|
|
100
|
+
'Not using OnPush change detection strategy',
|
|
101
|
+
'Calling functions in templates (runs on every change detection)',
|
|
102
|
+
'Not using trackBy in ngFor for large lists',
|
|
103
|
+
'Subscriptions not unsubscribed (memory leaks)',
|
|
104
|
+
'Manual change detection triggers overused'
|
|
105
|
+
],
|
|
106
|
+
rxjs: [
|
|
107
|
+
'Not unsubscribing from observables',
|
|
108
|
+
'Using subscribe() instead of async pipe in templates',
|
|
109
|
+
'Not using switchMap/mergeMap/concatMap correctly',
|
|
110
|
+
'Nested subscriptions (callback hell)',
|
|
111
|
+
'Missing error handling in subscribe()',
|
|
112
|
+
'Not using takeUntil for cleanup'
|
|
113
|
+
],
|
|
114
|
+
dependency_injection: [
|
|
115
|
+
'Services not marked with @Injectable()',
|
|
116
|
+
'Injecting in constructors instead of using inject() function',
|
|
117
|
+
'Missing providedIn metadata for tree-shaking',
|
|
118
|
+
'Circular dependencies between services'
|
|
119
|
+
]
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Python/Django framework patterns
|
|
124
|
+
*/
|
|
125
|
+
django: {
|
|
126
|
+
orm: [
|
|
127
|
+
'Raw SQL without parameterization (SQL injection risk)',
|
|
128
|
+
'N+1 queries (missing select_related/prefetch_related)',
|
|
129
|
+
'Synchronous database calls in async views',
|
|
130
|
+
'Using filter().count() instead of exists()',
|
|
131
|
+
'Not using bulk_create for multiple inserts',
|
|
132
|
+
'Missing database indexes on frequently queried fields',
|
|
133
|
+
'Using get() without DoesNotExist exception handling'
|
|
134
|
+
],
|
|
135
|
+
views: [
|
|
136
|
+
'Missing CSRF protection on forms',
|
|
137
|
+
'Not validating form data properly',
|
|
138
|
+
'Using GET requests for state-changing operations',
|
|
139
|
+
'Missing permission checks on views',
|
|
140
|
+
'Returning raw HTML instead of using templates',
|
|
141
|
+
'Not handling common HTTP status codes properly'
|
|
142
|
+
],
|
|
143
|
+
models: [
|
|
144
|
+
'Missing __str__ method on models',
|
|
145
|
+
'Not setting related_name on ForeignKey',
|
|
146
|
+
'Mutable default arguments (default=[] or default={})',
|
|
147
|
+
'Missing unique_together or Meta options',
|
|
148
|
+
'Using TextField instead of CharField with max_length',
|
|
149
|
+
'Missing choices for status fields'
|
|
150
|
+
],
|
|
151
|
+
security: [
|
|
152
|
+
'DEBUG=True in production',
|
|
153
|
+
'SECRET_KEY hardcoded or in version control',
|
|
154
|
+
'Missing ALLOWED_HOSTS configuration',
|
|
155
|
+
'Using eval() or exec() with user input',
|
|
156
|
+
'Not using Django ORM parameterization',
|
|
157
|
+
'Missing rate limiting on sensitive endpoints'
|
|
158
|
+
]
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* FastAPI framework patterns
|
|
163
|
+
*/
|
|
164
|
+
fastapi: {
|
|
165
|
+
async_patterns: [
|
|
166
|
+
'Mixing async and sync operations incorrectly',
|
|
167
|
+
'Using blocking I/O in async endpoints',
|
|
168
|
+
'Not using await with async database calls',
|
|
169
|
+
'Creating sync database sessions in async context',
|
|
170
|
+
'Missing async database driver'
|
|
171
|
+
],
|
|
172
|
+
validation: [
|
|
173
|
+
'Not using Pydantic models for request validation',
|
|
174
|
+
'Missing response models',
|
|
175
|
+
'Not validating query parameters',
|
|
176
|
+
'Returning raw dictionaries instead of models',
|
|
177
|
+
'Missing field validators for complex validation'
|
|
178
|
+
],
|
|
179
|
+
dependencies: [
|
|
180
|
+
'Dependency injection not used for database sessions',
|
|
181
|
+
'Not using Depends() for authentication',
|
|
182
|
+
'Missing dependency override for testing',
|
|
183
|
+
'Expensive operations in dependencies without caching'
|
|
184
|
+
]
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Rust patterns
|
|
189
|
+
*/
|
|
190
|
+
rust: {
|
|
191
|
+
safety: [
|
|
192
|
+
'Unsafe blocks without clear justification comment',
|
|
193
|
+
'Excessive use of unwrap() or expect() (prefer error handling)',
|
|
194
|
+
'Clone used when reference borrowing would work',
|
|
195
|
+
'Manual memory management when safe abstractions available',
|
|
196
|
+
'Transmute usage without clear safety invariants',
|
|
197
|
+
'Raw pointer dereferencing without bounds checking'
|
|
198
|
+
],
|
|
199
|
+
error_handling: [
|
|
200
|
+
'Using panic! in library code',
|
|
201
|
+
'Not implementing Error trait for custom errors',
|
|
202
|
+
'Ignoring Result types with underscore',
|
|
203
|
+
'Using unwrap() in production code paths',
|
|
204
|
+
'Missing ? operator for error propagation',
|
|
205
|
+
'Not providing context in error messages'
|
|
206
|
+
],
|
|
207
|
+
performance: [
|
|
208
|
+
'Unnecessary Vec allocations (use slices or arrays)',
|
|
209
|
+
'String concatenation in loops (use String::with_capacity)',
|
|
210
|
+
'Missing #[inline] on small hot functions',
|
|
211
|
+
'Not using iterators (manual loops)',
|
|
212
|
+
'Cloning when into() would transfer ownership',
|
|
213
|
+
'Not using Cow for conditional copying'
|
|
214
|
+
],
|
|
215
|
+
async_rust: [
|
|
216
|
+
'Blocking operations in async functions',
|
|
217
|
+
'Not using tokio::spawn for CPU-intensive work',
|
|
218
|
+
'Missing Send bounds on async trait methods',
|
|
219
|
+
'Holding locks across await points',
|
|
220
|
+
'Not using async-friendly versions of std types'
|
|
221
|
+
]
|
|
222
|
+
},
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Go patterns
|
|
226
|
+
*/
|
|
227
|
+
go: {
|
|
228
|
+
concurrency: [
|
|
229
|
+
'Goroutines without context cancellation',
|
|
230
|
+
'Mutex not unlocked in defer',
|
|
231
|
+
'Channels not closed properly',
|
|
232
|
+
'Race conditions in tests',
|
|
233
|
+
'WaitGroup.Add() called in wrong goroutine',
|
|
234
|
+
'Goroutine leaks (no cleanup mechanism)',
|
|
235
|
+
'Using global variables in concurrent code'
|
|
236
|
+
],
|
|
237
|
+
error_handling: [
|
|
238
|
+
'Ignored errors (using _ for error returns)',
|
|
239
|
+
'Error strings start with capital letter (go convention)',
|
|
240
|
+
'Not using fmt.Errorf with %w for error wrapping',
|
|
241
|
+
'Panic instead of returning error',
|
|
242
|
+
'Not checking errors from Close() or Flush()',
|
|
243
|
+
'Using panic/recover for control flow'
|
|
244
|
+
],
|
|
245
|
+
performance: [
|
|
246
|
+
'String concatenation in loops (use strings.Builder)',
|
|
247
|
+
'Not reusing buffers for repeated operations',
|
|
248
|
+
'Inefficient JSON marshaling in hot paths',
|
|
249
|
+
'Missing connection pooling for databases',
|
|
250
|
+
'Reflection used unnecessarily',
|
|
251
|
+
'Not using sync.Pool for frequent allocations'
|
|
252
|
+
],
|
|
253
|
+
best_practices: [
|
|
254
|
+
'Not using go fmt / go vet',
|
|
255
|
+
'Accepting interfaces, returning structs violation',
|
|
256
|
+
'Not embedding errors context',
|
|
257
|
+
'Using init() function unnecessarily',
|
|
258
|
+
'Exporting more than necessary',
|
|
259
|
+
'Not following effective Go guidelines'
|
|
260
|
+
]
|
|
261
|
+
},
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Express.js (Node.js) patterns
|
|
265
|
+
*/
|
|
266
|
+
express: {
|
|
267
|
+
async_handling: [
|
|
268
|
+
'Async route handlers not wrapped in try-catch',
|
|
269
|
+
'Not using async error handling middleware',
|
|
270
|
+
'Promises not awaited properly',
|
|
271
|
+
'Missing error handling in Promise chains',
|
|
272
|
+
'Sync code blocking event loop'
|
|
273
|
+
],
|
|
274
|
+
security: [
|
|
275
|
+
'Missing helmet middleware',
|
|
276
|
+
'No rate limiting on sensitive endpoints',
|
|
277
|
+
'CORS configured too permissively',
|
|
278
|
+
'User input not sanitized',
|
|
279
|
+
'SQL queries not parameterized',
|
|
280
|
+
'Passwords not hashed with bcrypt',
|
|
281
|
+
'Missing HTTPS in production',
|
|
282
|
+
'Exposing stack traces in production'
|
|
283
|
+
],
|
|
284
|
+
middleware: [
|
|
285
|
+
'Middleware order issues (e.g., body-parser position)',
|
|
286
|
+
'Not calling next() in middleware',
|
|
287
|
+
'Error middleware not having 4 parameters',
|
|
288
|
+
'Missing catch-all error handler',
|
|
289
|
+
'Middleware not handling async errors'
|
|
290
|
+
]
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
// Freeze the patterns object for V8 optimization
|
|
295
|
+
deepFreeze(reviewPatterns);
|
|
296
|
+
|
|
297
|
+
// ============================================================================
|
|
298
|
+
// Pre-indexed Maps for O(1) lookup performance (#18)
|
|
299
|
+
// Built once at module load time, avoiding iteration on every lookup
|
|
300
|
+
// ============================================================================
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Pre-indexed patterns by category across all frameworks
|
|
304
|
+
* Key: category name (e.g., 'security', 'performance', 'error_handling')
|
|
305
|
+
* Value: Map of framework -> array of patterns
|
|
306
|
+
*/
|
|
307
|
+
const _patternsByCategory = new Map();
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Set of all frameworks for O(1) existence check
|
|
311
|
+
*/
|
|
312
|
+
const _frameworksSet = new Set(Object.keys(reviewPatterns));
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Set of all categories across all frameworks
|
|
316
|
+
*/
|
|
317
|
+
const _categoriesSet = new Set();
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Count of patterns per framework for quick stats
|
|
321
|
+
*/
|
|
322
|
+
const _patternCountByFramework = new Map();
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Flattened pattern index for full-text search
|
|
326
|
+
* Key: framework
|
|
327
|
+
* Value: array of { category, pattern } for all patterns
|
|
328
|
+
*/
|
|
329
|
+
const _flattenedPatterns = new Map();
|
|
330
|
+
|
|
331
|
+
// Build indexes at module load time
|
|
332
|
+
(function buildIndexes() {
|
|
333
|
+
for (const [framework, categories] of Object.entries(reviewPatterns)) {
|
|
334
|
+
let totalPatterns = 0;
|
|
335
|
+
const flattened = [];
|
|
336
|
+
|
|
337
|
+
for (const [category, patterns] of Object.entries(categories)) {
|
|
338
|
+
_categoriesSet.add(category);
|
|
339
|
+
|
|
340
|
+
// Index by category
|
|
341
|
+
if (!_patternsByCategory.has(category)) {
|
|
342
|
+
_patternsByCategory.set(category, new Map());
|
|
343
|
+
}
|
|
344
|
+
_patternsByCategory.get(category).set(framework, patterns);
|
|
345
|
+
|
|
346
|
+
// Count patterns
|
|
347
|
+
totalPatterns += patterns.length;
|
|
348
|
+
|
|
349
|
+
// Flatten for search
|
|
350
|
+
for (const pattern of patterns) {
|
|
351
|
+
flattened.push({ category, pattern });
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
_patternCountByFramework.set(framework, totalPatterns);
|
|
356
|
+
_flattenedPatterns.set(framework, flattened);
|
|
357
|
+
}
|
|
358
|
+
})();
|
|
359
|
+
|
|
360
|
+
// Freeze the index Sets
|
|
361
|
+
Object.freeze(_frameworksSet);
|
|
362
|
+
Object.freeze(_categoriesSet);
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Get review patterns for a detected framework (O(1) lookup)
|
|
366
|
+
* @param {string} framework - Framework name
|
|
367
|
+
* @returns {Object|null} Patterns for framework or null if not found
|
|
368
|
+
*/
|
|
369
|
+
function getPatternsForFramework(framework) {
|
|
370
|
+
if (typeof framework !== 'string') return null;
|
|
371
|
+
return reviewPatterns[framework.toLowerCase()] || null;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Get patterns for a specific category across all frameworks
|
|
376
|
+
* @param {string} category - Category name (e.g., 'security', 'performance')
|
|
377
|
+
* @returns {Map<string, Array>} Map of framework -> patterns for that category
|
|
378
|
+
*/
|
|
379
|
+
function getPatternsByCategory(category) {
|
|
380
|
+
return _patternsByCategory.get(category) || new Map();
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Get patterns for a framework and category combination (O(1) lookup)
|
|
385
|
+
* @param {string} framework - Framework name
|
|
386
|
+
* @param {string} category - Category name
|
|
387
|
+
* @returns {Array|null} Array of pattern strings or null
|
|
388
|
+
*/
|
|
389
|
+
function getPatternsForFrameworkCategory(framework, category) {
|
|
390
|
+
const frameworkPatterns = reviewPatterns[framework.toLowerCase()];
|
|
391
|
+
if (!frameworkPatterns) return null;
|
|
392
|
+
return frameworkPatterns[category] || null;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Get all available frameworks (O(1) via pre-computed Set)
|
|
397
|
+
* @returns {Array<string>} List of framework names
|
|
398
|
+
*/
|
|
399
|
+
function getAvailableFrameworks() {
|
|
400
|
+
return Array.from(_frameworksSet);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Get all available categories across all frameworks
|
|
405
|
+
* @returns {Array<string>} List of category names
|
|
406
|
+
*/
|
|
407
|
+
function getAvailableCategories() {
|
|
408
|
+
return Array.from(_categoriesSet);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Get categories available for a specific framework
|
|
413
|
+
* @param {string} framework - Framework name
|
|
414
|
+
* @returns {Array<string>} List of category names for the framework
|
|
415
|
+
*/
|
|
416
|
+
function getCategoriesForFramework(framework) {
|
|
417
|
+
const frameworkPatterns = reviewPatterns[framework.toLowerCase()];
|
|
418
|
+
if (!frameworkPatterns) return [];
|
|
419
|
+
return Object.keys(frameworkPatterns);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Check if patterns exist for a framework (O(1) lookup)
|
|
424
|
+
* @param {string} framework - Framework name
|
|
425
|
+
* @returns {boolean} True if patterns available
|
|
426
|
+
*/
|
|
427
|
+
function hasPatternsFor(framework) {
|
|
428
|
+
if (typeof framework !== 'string') return false;
|
|
429
|
+
return _frameworksSet.has(framework.toLowerCase());
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Check if a category exists across any framework (O(1) lookup)
|
|
434
|
+
* @param {string} category - Category name
|
|
435
|
+
* @returns {boolean} True if category exists
|
|
436
|
+
*/
|
|
437
|
+
function hasCategory(category) {
|
|
438
|
+
return _categoriesSet.has(category);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Get pattern count for a framework
|
|
443
|
+
* @param {string} framework - Framework name
|
|
444
|
+
* @returns {number} Number of patterns
|
|
445
|
+
*/
|
|
446
|
+
function getPatternCount(framework) {
|
|
447
|
+
return _patternCountByFramework.get(framework.toLowerCase()) || 0;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Get total pattern count across all frameworks
|
|
452
|
+
* @returns {number} Total pattern count
|
|
453
|
+
*/
|
|
454
|
+
function getTotalPatternCount() {
|
|
455
|
+
let total = 0;
|
|
456
|
+
for (const count of _patternCountByFramework.values()) {
|
|
457
|
+
total += count;
|
|
458
|
+
}
|
|
459
|
+
return total;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Search patterns by keyword across all frameworks
|
|
464
|
+
* @param {string} keyword - Search term (case-insensitive)
|
|
465
|
+
* @returns {Array<{framework: string, category: string, pattern: string}>} Matching patterns
|
|
466
|
+
*/
|
|
467
|
+
function searchPatterns(keyword) {
|
|
468
|
+
const lowerKeyword = keyword.toLowerCase();
|
|
469
|
+
const results = [];
|
|
470
|
+
|
|
471
|
+
for (const [framework, patterns] of _flattenedPatterns) {
|
|
472
|
+
for (const { category, pattern } of patterns) {
|
|
473
|
+
if (pattern.toLowerCase().includes(lowerKeyword)) {
|
|
474
|
+
results.push({ framework, category, pattern });
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
return results;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Get frameworks that have a specific category
|
|
484
|
+
* @param {string} category - Category name
|
|
485
|
+
* @returns {Array<string>} List of frameworks with this category
|
|
486
|
+
*/
|
|
487
|
+
function getFrameworksWithCategory(category) {
|
|
488
|
+
const categoryMap = _patternsByCategory.get(category);
|
|
489
|
+
if (!categoryMap) return [];
|
|
490
|
+
return Array.from(categoryMap.keys());
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
module.exports = {
|
|
494
|
+
reviewPatterns,
|
|
495
|
+
// Pre-indexed lookup functions (O(1) performance)
|
|
496
|
+
getPatternsForFramework,
|
|
497
|
+
getPatternsByCategory,
|
|
498
|
+
getPatternsForFrameworkCategory,
|
|
499
|
+
// Metadata functions
|
|
500
|
+
getAvailableFrameworks,
|
|
501
|
+
getAvailableCategories,
|
|
502
|
+
getCategoriesForFramework,
|
|
503
|
+
hasPatternsFor,
|
|
504
|
+
hasCategory,
|
|
505
|
+
// Stats functions
|
|
506
|
+
getPatternCount,
|
|
507
|
+
getTotalPatternCount,
|
|
508
|
+
// Search functions
|
|
509
|
+
searchPatterns,
|
|
510
|
+
getFrameworksWithCategory
|
|
511
|
+
};
|