@houtini/lm 1.0.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/CHANGELOG.md +273 -0
- package/LICENSE +21 -0
- package/README.md +203 -0
- package/dist/cache/analysis-cache.d.ts +33 -0
- package/dist/cache/analysis-cache.d.ts.map +1 -0
- package/dist/cache/analysis-cache.js +56 -0
- package/dist/cache/analysis-cache.js.map +1 -0
- package/dist/cache/cache-manager.d.ts +29 -0
- package/dist/cache/cache-manager.d.ts.map +1 -0
- package/dist/cache/cache-manager.js +85 -0
- package/dist/cache/cache-manager.js.map +1 -0
- package/dist/cache/index.d.ts +16 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +17 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/prompt-cache.d.ts +33 -0
- package/dist/cache/prompt-cache.d.ts.map +1 -0
- package/dist/cache/prompt-cache.js +61 -0
- package/dist/cache/prompt-cache.js.map +1 -0
- package/dist/config.d.ts +43 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +70 -0
- package/dist/config.js.map +1 -0
- package/dist/core/ThreeStagePromptManager.d.ts +39 -0
- package/dist/core/ThreeStagePromptManager.d.ts.map +1 -0
- package/dist/core/ThreeStagePromptManager.js +176 -0
- package/dist/core/ThreeStagePromptManager.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +230 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/base-plugin.d.ts +47 -0
- package/dist/plugins/base-plugin.d.ts.map +1 -0
- package/dist/plugins/base-plugin.js +90 -0
- package/dist/plugins/base-plugin.js.map +1 -0
- package/dist/plugins/index.d.ts +58 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +161 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/types.d.ts +5 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +5 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/prompts/analyze/code-quality.d.ts +116 -0
- package/dist/prompts/analyze/code-quality.d.ts.map +1 -0
- package/dist/prompts/analyze/code-quality.js +433 -0
- package/dist/prompts/analyze/code-quality.js.map +1 -0
- package/dist/prompts/analyze/compare-integration.d.ts +130 -0
- package/dist/prompts/analyze/compare-integration.d.ts.map +1 -0
- package/dist/prompts/analyze/compare-integration.js +543 -0
- package/dist/prompts/analyze/compare-integration.js.map +1 -0
- package/dist/prompts/analyze/count-files.d.ts +109 -0
- package/dist/prompts/analyze/count-files.d.ts.map +1 -0
- package/dist/prompts/analyze/count-files.js +399 -0
- package/dist/prompts/analyze/count-files.js.map +1 -0
- package/dist/prompts/analyze/database-queries.d.ts +156 -0
- package/dist/prompts/analyze/database-queries.d.ts.map +1 -0
- package/dist/prompts/analyze/database-queries.js +759 -0
- package/dist/prompts/analyze/database-queries.js.map +1 -0
- package/dist/prompts/analyze/dependencies.d.ts +97 -0
- package/dist/prompts/analyze/dependencies.d.ts.map +1 -0
- package/dist/prompts/analyze/dependencies.js +333 -0
- package/dist/prompts/analyze/dependencies.js.map +1 -0
- package/dist/prompts/analyze/diff-signatures.d.ts +139 -0
- package/dist/prompts/analyze/diff-signatures.d.ts.map +1 -0
- package/dist/prompts/analyze/diff-signatures.js +702 -0
- package/dist/prompts/analyze/diff-signatures.js.map +1 -0
- package/dist/prompts/analyze/find-patterns.d.ts +128 -0
- package/dist/prompts/analyze/find-patterns.d.ts.map +1 -0
- package/dist/prompts/analyze/find-patterns.js +520 -0
- package/dist/prompts/analyze/find-patterns.js.map +1 -0
- package/dist/prompts/analyze/find-unused-css.d.ts +151 -0
- package/dist/prompts/analyze/find-unused-css.d.ts.map +1 -0
- package/dist/prompts/analyze/find-unused-css.js +754 -0
- package/dist/prompts/analyze/find-unused-css.js.map +1 -0
- package/dist/prompts/analyze/n8n-workflow.d.ts +137 -0
- package/dist/prompts/analyze/n8n-workflow.d.ts.map +1 -0
- package/dist/prompts/analyze/n8n-workflow.js +529 -0
- package/dist/prompts/analyze/n8n-workflow.js.map +1 -0
- package/dist/prompts/analyze/project-structure.d.ts +126 -0
- package/dist/prompts/analyze/project-structure.d.ts.map +1 -0
- package/dist/prompts/analyze/project-structure.js +569 -0
- package/dist/prompts/analyze/project-structure.js.map +1 -0
- package/dist/prompts/analyze/security-audit.d.ts +142 -0
- package/dist/prompts/analyze/security-audit.d.ts.map +1 -0
- package/dist/prompts/analyze/security-audit.js +637 -0
- package/dist/prompts/analyze/security-audit.js.map +1 -0
- package/dist/prompts/analyze/single-file.d.ts +162 -0
- package/dist/prompts/analyze/single-file.d.ts.map +1 -0
- package/dist/prompts/analyze/single-file.js +665 -0
- package/dist/prompts/analyze/single-file.js.map +1 -0
- package/dist/prompts/analyze/trace-execution.d.ts +126 -0
- package/dist/prompts/analyze/trace-execution.d.ts.map +1 -0
- package/dist/prompts/analyze/trace-execution.js +609 -0
- package/dist/prompts/analyze/trace-execution.js.map +1 -0
- package/dist/prompts/analyze/wordpress-plugin-audit.d.ts +116 -0
- package/dist/prompts/analyze/wordpress-plugin-audit.d.ts.map +1 -0
- package/dist/prompts/analyze/wordpress-plugin-audit.js +454 -0
- package/dist/prompts/analyze/wordpress-plugin-audit.js.map +1 -0
- package/dist/prompts/analyze/wordpress-security.d.ts +146 -0
- package/dist/prompts/analyze/wordpress-security.d.ts.map +1 -0
- package/dist/prompts/analyze/wordpress-security.js +698 -0
- package/dist/prompts/analyze/wordpress-security.js.map +1 -0
- package/dist/prompts/analyze/wordpress-theme-audit.d.ts +114 -0
- package/dist/prompts/analyze/wordpress-theme-audit.d.ts.map +1 -0
- package/dist/prompts/analyze/wordpress-theme-audit.js +538 -0
- package/dist/prompts/analyze/wordpress-theme-audit.js.map +1 -0
- package/dist/prompts/custom/custom-prompt.d.ts +135 -0
- package/dist/prompts/custom/custom-prompt.d.ts.map +1 -0
- package/dist/prompts/custom/custom-prompt.js +419 -0
- package/dist/prompts/custom/custom-prompt.js.map +1 -0
- package/dist/prompts/fun/arcade-game.d.ts +152 -0
- package/dist/prompts/fun/arcade-game.d.ts.map +1 -0
- package/dist/prompts/fun/arcade-game.js +653 -0
- package/dist/prompts/fun/arcade-game.js.map +1 -0
- package/dist/prompts/fun/create_text_adventure.d.ts +100 -0
- package/dist/prompts/fun/create_text_adventure.d.ts.map +1 -0
- package/dist/prompts/fun/create_text_adventure.js +397 -0
- package/dist/prompts/fun/create_text_adventure.js.map +1 -0
- package/dist/prompts/fun/css-art-generator.d.ts +168 -0
- package/dist/prompts/fun/css-art-generator.d.ts.map +1 -0
- package/dist/prompts/fun/css-art-generator.js +827 -0
- package/dist/prompts/fun/css-art-generator.js.map +1 -0
- package/dist/prompts/generate/project-documentation.d.ts +137 -0
- package/dist/prompts/generate/project-documentation.d.ts.map +1 -0
- package/dist/prompts/generate/project-documentation.js +666 -0
- package/dist/prompts/generate/project-documentation.js.map +1 -0
- package/dist/prompts/generate/refactoring.d.ts +164 -0
- package/dist/prompts/generate/refactoring.d.ts.map +1 -0
- package/dist/prompts/generate/refactoring.js +621 -0
- package/dist/prompts/generate/refactoring.js.map +1 -0
- package/dist/prompts/generate/responsive-component.d.ts +147 -0
- package/dist/prompts/generate/responsive-component.d.ts.map +1 -0
- package/dist/prompts/generate/responsive-component.js +955 -0
- package/dist/prompts/generate/responsive-component.js.map +1 -0
- package/dist/prompts/generate/typescript-conversion.d.ts +144 -0
- package/dist/prompts/generate/typescript-conversion.d.ts.map +1 -0
- package/dist/prompts/generate/typescript-conversion.js +527 -0
- package/dist/prompts/generate/typescript-conversion.js.map +1 -0
- package/dist/prompts/generate/unit-tests.d.ts +139 -0
- package/dist/prompts/generate/unit-tests.d.ts.map +1 -0
- package/dist/prompts/generate/unit-tests.js +578 -0
- package/dist/prompts/generate/unit-tests.js.map +1 -0
- package/dist/prompts/generate/wordpress-plugin.d.ts +179 -0
- package/dist/prompts/generate/wordpress-plugin.d.ts.map +1 -0
- package/dist/prompts/generate/wordpress-plugin.js +763 -0
- package/dist/prompts/generate/wordpress-plugin.js.map +1 -0
- package/dist/prompts/generate/wordpress-theme-from-static.d.ts +177 -0
- package/dist/prompts/generate/wordpress-theme-from-static.d.ts.map +1 -0
- package/dist/prompts/generate/wordpress-theme-from-static.js +695 -0
- package/dist/prompts/generate/wordpress-theme-from-static.js.map +1 -0
- package/dist/prompts/shared/cache-manager.d.ts +45 -0
- package/dist/prompts/shared/cache-manager.d.ts.map +1 -0
- package/dist/prompts/shared/cache-manager.js +129 -0
- package/dist/prompts/shared/cache-manager.js.map +1 -0
- package/dist/prompts/shared/helpers.d.ts +39 -0
- package/dist/prompts/shared/helpers.d.ts.map +1 -0
- package/dist/prompts/shared/helpers.js +151 -0
- package/dist/prompts/shared/helpers.js.map +1 -0
- package/dist/prompts/shared/templates.d.ts +35 -0
- package/dist/prompts/shared/templates.d.ts.map +1 -0
- package/dist/prompts/shared/templates.js +77 -0
- package/dist/prompts/shared/templates.js.map +1 -0
- package/dist/prompts/shared/types.d.ts +112 -0
- package/dist/prompts/shared/types.d.ts.map +1 -0
- package/dist/prompts/shared/types.js +5 -0
- package/dist/prompts/shared/types.js.map +1 -0
- package/dist/prompts/system/find-unused-files.d.ts +106 -0
- package/dist/prompts/system/find-unused-files.d.ts.map +1 -0
- package/dist/prompts/system/find-unused-files.js +353 -0
- package/dist/prompts/system/find-unused-files.js.map +1 -0
- package/dist/security/index.d.ts +39 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +46 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/integration-helpers.d.ts +121 -0
- package/dist/security/integration-helpers.d.ts.map +1 -0
- package/dist/security/integration-helpers.js +190 -0
- package/dist/security/integration-helpers.js.map +1 -0
- package/dist/security/output-encoder.d.ts +94 -0
- package/dist/security/output-encoder.d.ts.map +1 -0
- package/dist/security/output-encoder.js +295 -0
- package/dist/security/output-encoder.js.map +1 -0
- package/dist/security/prompt-injection-guard.d.ts +59 -0
- package/dist/security/prompt-injection-guard.d.ts.map +1 -0
- package/dist/security/prompt-injection-guard.js +249 -0
- package/dist/security/prompt-injection-guard.js.map +1 -0
- package/dist/security/sanitisation.d.ts +67 -0
- package/dist/security/sanitisation.d.ts.map +1 -0
- package/dist/security/sanitisation.js +398 -0
- package/dist/security/sanitisation.js.map +1 -0
- package/dist/security/security-service.d.ts +103 -0
- package/dist/security/security-service.d.ts.map +1 -0
- package/dist/security/security-service.js +303 -0
- package/dist/security/security-service.js.map +1 -0
- package/dist/security-config.d.ts +45 -0
- package/dist/security-config.d.ts.map +1 -0
- package/dist/security-config.js +63 -0
- package/dist/security-config.js.map +1 -0
- package/dist/system/function-list.d.ts +61 -0
- package/dist/system/function-list.d.ts.map +1 -0
- package/dist/system/function-list.js +111 -0
- package/dist/system/function-list.js.map +1 -0
- package/dist/system/function-registry.d.ts +23 -0
- package/dist/system/function-registry.d.ts.map +1 -0
- package/dist/system/function-registry.js +136 -0
- package/dist/system/function-registry.js.map +1 -0
- package/dist/system/health-check.d.ts +33 -0
- package/dist/system/health-check.d.ts.map +1 -0
- package/dist/system/health-check.js +98 -0
- package/dist/system/health-check.js.map +1 -0
- package/dist/system/path-resolver.d.ts +55 -0
- package/dist/system/path-resolver.d.ts.map +1 -0
- package/dist/system/path-resolver.js +90 -0
- package/dist/system/path-resolver.js.map +1 -0
- package/dist/templates/plugin-template.d.ts +121 -0
- package/dist/templates/plugin-template.d.ts.map +1 -0
- package/dist/templates/plugin-template.js +450 -0
- package/dist/templates/plugin-template.js.map +1 -0
- package/dist/types/chunking-types.d.ts +88 -0
- package/dist/types/chunking-types.d.ts.map +1 -0
- package/dist/types/chunking-types.js +18 -0
- package/dist/types/chunking-types.js.map +1 -0
- package/dist/types/prompt-stages.d.ts +42 -0
- package/dist/types/prompt-stages.d.ts.map +1 -0
- package/dist/types/prompt-stages.js +6 -0
- package/dist/types/prompt-stages.js.map +1 -0
- package/dist/types.d.ts +46 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/css-parser.d.ts +26 -0
- package/dist/utils/css-parser.d.ts.map +1 -0
- package/dist/utils/css-parser.js +117 -0
- package/dist/utils/css-parser.js.map +1 -0
- package/dist/utils/path-resolver.d.ts +13 -0
- package/dist/utils/path-resolver.d.ts.map +1 -0
- package/dist/utils/path-resolver.js +78 -0
- package/dist/utils/path-resolver.js.map +1 -0
- package/dist/utils/plugin-utilities.d.ts +171 -0
- package/dist/utils/plugin-utilities.d.ts.map +1 -0
- package/dist/utils/plugin-utilities.js +221 -0
- package/dist/utils/plugin-utilities.js.map +1 -0
- package/dist/utils/streamHandler.d.ts +3 -0
- package/dist/utils/streamHandler.d.ts.map +1 -0
- package/dist/utils/streamHandler.js +137 -0
- package/dist/utils/streamHandler.js.map +1 -0
- package/dist/validation/output-validator.d.ts +136 -0
- package/dist/validation/output-validator.d.ts.map +1 -0
- package/dist/validation/output-validator.js +262 -0
- package/dist/validation/output-validator.js.map +1 -0
- package/dist/validation/response-factory.d.ts +44 -0
- package/dist/validation/response-factory.d.ts.map +1 -0
- package/dist/validation/response-factory.js +202 -0
- package/dist/validation/response-factory.js.map +1 -0
- package/dist/validation/schemas.d.ts +519 -0
- package/dist/validation/schemas.d.ts.map +1 -0
- package/dist/validation/schemas.js +6 -0
- package/dist/validation/schemas.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,759 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin Template - Modern v4.2 (Single Source of Truth)
|
|
3
|
+
*
|
|
4
|
+
* Universal template that intelligently handles both single-file and multi-file analysis
|
|
5
|
+
* Automatically detects analysis type based on provided parameters
|
|
6
|
+
*
|
|
7
|
+
* Copy this template for creating any new plugin - it adapts to your needs
|
|
8
|
+
*/
|
|
9
|
+
import { BasePlugin } from '../../plugins/base-plugin.js';
|
|
10
|
+
import { ThreeStagePromptManager } from '../../core/ThreeStagePromptManager.js';
|
|
11
|
+
import { withSecurity } from '../../security/integration-helpers.js';
|
|
12
|
+
import { readFileContent } from '../shared/helpers.js';
|
|
13
|
+
import { ModelSetup, ResponseProcessor, ParameterValidator, ErrorHandler, MultiFileAnalysis } from '../../utils/plugin-utilities.js';
|
|
14
|
+
import { getAnalysisCache } from '../../cache/index.js';
|
|
15
|
+
// Common Node.js modules - Use these instead of require()
|
|
16
|
+
import { basename, extname, relative } from 'path';
|
|
17
|
+
import { readFile, stat } from 'fs/promises';
|
|
18
|
+
export class DatabaseQueryAnalyzer extends BasePlugin {
|
|
19
|
+
constructor() {
|
|
20
|
+
super();
|
|
21
|
+
this.name = 'analyze_database_queries';
|
|
22
|
+
this.category = 'analyze';
|
|
23
|
+
this.description = 'Analyze database queries for performance, security, and best practices in code files or entire projects';
|
|
24
|
+
// Universal parameter set - supports both single and multi-file scenarios
|
|
25
|
+
this.parameters = {
|
|
26
|
+
// Single-file parameters
|
|
27
|
+
code: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
description: 'The code to analyze for database queries (for single-file analysis)',
|
|
30
|
+
required: false
|
|
31
|
+
},
|
|
32
|
+
filePath: {
|
|
33
|
+
type: 'string',
|
|
34
|
+
description: 'Path to single file to analyze for database queries',
|
|
35
|
+
required: false
|
|
36
|
+
},
|
|
37
|
+
// Multi-file parameters
|
|
38
|
+
projectPath: {
|
|
39
|
+
type: 'string',
|
|
40
|
+
description: 'Path to project root (for multi-file database analysis)',
|
|
41
|
+
required: false
|
|
42
|
+
},
|
|
43
|
+
files: {
|
|
44
|
+
type: 'array',
|
|
45
|
+
description: 'Array of specific file paths (for multi-file analysis)',
|
|
46
|
+
required: false,
|
|
47
|
+
items: { type: 'string' }
|
|
48
|
+
},
|
|
49
|
+
maxDepth: {
|
|
50
|
+
type: 'number',
|
|
51
|
+
description: 'Maximum directory depth for multi-file discovery (1-5)',
|
|
52
|
+
required: false,
|
|
53
|
+
default: 3
|
|
54
|
+
},
|
|
55
|
+
// Universal parameters
|
|
56
|
+
language: {
|
|
57
|
+
type: 'string',
|
|
58
|
+
description: 'Programming language',
|
|
59
|
+
required: false,
|
|
60
|
+
default: 'php'
|
|
61
|
+
},
|
|
62
|
+
analysisDepth: {
|
|
63
|
+
type: 'string',
|
|
64
|
+
description: 'Level of analysis detail',
|
|
65
|
+
enum: ['basic', 'detailed', 'comprehensive'],
|
|
66
|
+
default: 'detailed',
|
|
67
|
+
required: false
|
|
68
|
+
},
|
|
69
|
+
analysisType: {
|
|
70
|
+
type: 'string',
|
|
71
|
+
description: 'Type of database analysis to perform',
|
|
72
|
+
enum: ['security', 'performance', 'best-practices', 'comprehensive'],
|
|
73
|
+
default: 'comprehensive',
|
|
74
|
+
required: false
|
|
75
|
+
},
|
|
76
|
+
// Database-specific parameters
|
|
77
|
+
context: {
|
|
78
|
+
type: 'object',
|
|
79
|
+
description: 'Database and framework context for specialized analysis',
|
|
80
|
+
required: false,
|
|
81
|
+
properties: {
|
|
82
|
+
database: {
|
|
83
|
+
type: 'string',
|
|
84
|
+
enum: ['mysql', 'postgresql', 'sqlite', 'mongodb', 'generic'],
|
|
85
|
+
description: 'Database engine for engine-specific optimizations'
|
|
86
|
+
},
|
|
87
|
+
framework: {
|
|
88
|
+
type: 'string',
|
|
89
|
+
enum: ['wordpress', 'laravel', 'symfony', 'django', 'rails', 'express', 'generic'],
|
|
90
|
+
description: 'Framework for framework-specific query patterns'
|
|
91
|
+
},
|
|
92
|
+
orm: {
|
|
93
|
+
type: 'string',
|
|
94
|
+
enum: ['eloquent', 'doctrine', 'sequelize', 'mongoose', 'activerecord', 'none'],
|
|
95
|
+
description: 'ORM/Query builder being used'
|
|
96
|
+
},
|
|
97
|
+
environment: {
|
|
98
|
+
type: 'string',
|
|
99
|
+
enum: ['development', 'staging', 'production'],
|
|
100
|
+
description: 'Environment context for performance recommendations'
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
this.analysisCache = getAnalysisCache();
|
|
106
|
+
this.multiFileAnalysis = new MultiFileAnalysis();
|
|
107
|
+
// Cache and analysis utilities are initialized above
|
|
108
|
+
}
|
|
109
|
+
async execute(params, llmClient) {
|
|
110
|
+
return await withSecurity(this, params, llmClient, async (secureParams) => {
|
|
111
|
+
try {
|
|
112
|
+
// 1. Auto-detect analysis mode based on parameters
|
|
113
|
+
const analysisMode = this.detectAnalysisMode(secureParams);
|
|
114
|
+
// 2. Validate parameters based on detected mode
|
|
115
|
+
this.validateParameters(secureParams, analysisMode);
|
|
116
|
+
// 3. Setup model
|
|
117
|
+
const { model, contextLength } = await ModelSetup.getReadyModel(llmClient);
|
|
118
|
+
// 4. Route to appropriate analysis method
|
|
119
|
+
if (analysisMode === 'single-file') {
|
|
120
|
+
return await this.executeSingleFileAnalysis(secureParams, model, contextLength);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
return await this.executeMultiFileAnalysis(secureParams, model, contextLength);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
return ErrorHandler.createExecutionError('analyze_database_queries', error);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Auto-detect whether this is single-file or multi-file analysis
|
|
133
|
+
*/
|
|
134
|
+
detectAnalysisMode(params) {
|
|
135
|
+
// Single-file indicators take priority
|
|
136
|
+
if (params.code || params.filePath) {
|
|
137
|
+
return 'single-file';
|
|
138
|
+
}
|
|
139
|
+
// Multi-file indicators
|
|
140
|
+
if (params.projectPath || params.files) {
|
|
141
|
+
return 'multi-file';
|
|
142
|
+
}
|
|
143
|
+
// Default to single-file for focused query analysis
|
|
144
|
+
return 'single-file';
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Validate parameters based on detected analysis mode
|
|
148
|
+
*/
|
|
149
|
+
validateParameters(params, mode) {
|
|
150
|
+
if (mode === 'single-file') {
|
|
151
|
+
ParameterValidator.validateCodeOrFile(params);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
ParameterValidator.validateProjectPath(params);
|
|
155
|
+
ParameterValidator.validateDepth(params);
|
|
156
|
+
}
|
|
157
|
+
// Universal validations
|
|
158
|
+
ParameterValidator.validateEnum(params, 'analysisType', ['security', 'performance', 'best-practices', 'comprehensive']);
|
|
159
|
+
ParameterValidator.validateEnum(params, 'analysisDepth', ['basic', 'detailed', 'comprehensive']);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Execute single-file analysis
|
|
163
|
+
*/
|
|
164
|
+
async executeSingleFileAnalysis(params, model, contextLength) {
|
|
165
|
+
// Process single file input
|
|
166
|
+
let codeToAnalyze = params.code;
|
|
167
|
+
if (params.filePath) {
|
|
168
|
+
codeToAnalyze = await readFileContent(params.filePath);
|
|
169
|
+
}
|
|
170
|
+
// Extract database queries from the code
|
|
171
|
+
const extractedQueries = this.extractDatabaseQueries(codeToAnalyze, params.language, params.context);
|
|
172
|
+
// Generate prompt stages for single file
|
|
173
|
+
const promptStages = this.getSingleFilePromptStages({
|
|
174
|
+
...params,
|
|
175
|
+
code: codeToAnalyze,
|
|
176
|
+
extractedQueries
|
|
177
|
+
});
|
|
178
|
+
// Execute with appropriate method
|
|
179
|
+
const promptManager = new ThreeStagePromptManager(contextLength);
|
|
180
|
+
const needsChunking = promptManager.needsChunking(promptStages);
|
|
181
|
+
if (needsChunking) {
|
|
182
|
+
const conversation = promptManager.createChunkedConversation(promptStages);
|
|
183
|
+
const messages = [
|
|
184
|
+
conversation.systemMessage,
|
|
185
|
+
...conversation.dataMessages,
|
|
186
|
+
conversation.analysisMessage
|
|
187
|
+
];
|
|
188
|
+
return await ResponseProcessor.executeChunked(messages, model, contextLength, 'analyze_database_queries', 'single');
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
return await ResponseProcessor.executeDirect(promptStages, model, contextLength, 'analyze_database_queries');
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Execute multi-file analysis
|
|
196
|
+
*/
|
|
197
|
+
async executeMultiFileAnalysis(params, model, contextLength) {
|
|
198
|
+
// Discover files
|
|
199
|
+
let filesToAnalyze = params.files ||
|
|
200
|
+
await this.discoverRelevantFiles(params.projectPath, params.maxDepth, params.analysisType);
|
|
201
|
+
// Perform multi-file analysis with caching
|
|
202
|
+
const analysisResult = await this.performMultiFileAnalysis(filesToAnalyze, params, model, contextLength);
|
|
203
|
+
// Generate prompt stages for multi-file
|
|
204
|
+
const promptStages = this.getMultiFilePromptStages({
|
|
205
|
+
...params,
|
|
206
|
+
analysisResult,
|
|
207
|
+
fileCount: filesToAnalyze.length
|
|
208
|
+
});
|
|
209
|
+
// Always use chunking for multi-file
|
|
210
|
+
const promptManager = new ThreeStagePromptManager(contextLength);
|
|
211
|
+
const conversation = promptManager.createChunkedConversation(promptStages);
|
|
212
|
+
const messages = [
|
|
213
|
+
conversation.systemMessage,
|
|
214
|
+
...conversation.dataMessages,
|
|
215
|
+
conversation.analysisMessage
|
|
216
|
+
];
|
|
217
|
+
return await ResponseProcessor.executeChunked(messages, model, contextLength, 'analyze_database_queries', 'multifile');
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Database Query Analysis - Single File Expert Analysis
|
|
221
|
+
*/
|
|
222
|
+
getSingleFilePromptStages(params) {
|
|
223
|
+
const { code, language, analysisDepth, analysisType, extractedQueries, filePath, context = {} } = params;
|
|
224
|
+
const database = context.database || 'generic';
|
|
225
|
+
const framework = context.framework || 'generic';
|
|
226
|
+
const orm = context.orm || 'none';
|
|
227
|
+
const environment = context.environment || 'production';
|
|
228
|
+
const systemAndContext = `You are a world-class database performance expert and security specialist with 20+ years of experience optimizing database queries across all major platforms.
|
|
229
|
+
|
|
230
|
+
**DATABASE ANALYSIS CONTEXT:**
|
|
231
|
+
- Database Engine: ${database}
|
|
232
|
+
- Framework: ${framework}
|
|
233
|
+
- ORM/Query Builder: ${orm}
|
|
234
|
+
- Programming Language: ${language}
|
|
235
|
+
- Environment: ${environment}
|
|
236
|
+
- Analysis Focus: ${analysisType}
|
|
237
|
+
- Analysis Depth: ${analysisDepth}
|
|
238
|
+
- File: ${filePath ? basename(filePath) : 'inline code'}
|
|
239
|
+
|
|
240
|
+
**YOUR EXPERTISE:**
|
|
241
|
+
You are recognized as a leading expert in:
|
|
242
|
+
- SQL query optimization and execution plan analysis
|
|
243
|
+
- Database security and injection prevention
|
|
244
|
+
- Framework-specific query patterns (WordPress $wpdb, Laravel Eloquent, etc.)
|
|
245
|
+
- Performance bottleneck identification and resolution
|
|
246
|
+
- Index strategy and database schema optimization
|
|
247
|
+
- N+1 query problem detection and solutions
|
|
248
|
+
- Query caching strategies and implementation
|
|
249
|
+
- Database-specific optimization techniques for ${database}
|
|
250
|
+
|
|
251
|
+
${this.getDatabaseSpecificInstructions(database, framework, orm)}
|
|
252
|
+
|
|
253
|
+
**ANALYSIS APPROACH:**
|
|
254
|
+
1. **Query Detection**: Identify all database queries in the code
|
|
255
|
+
2. **Security Assessment**: Evaluate for SQL injection vulnerabilities
|
|
256
|
+
3. **Performance Analysis**: Identify bottlenecks, N+1 problems, and optimization opportunities
|
|
257
|
+
4. **Best Practices Review**: Check against framework and database best practices
|
|
258
|
+
5. **Actionable Recommendations**: Provide specific, implementable improvements with examples
|
|
259
|
+
|
|
260
|
+
You provide expert-level analysis that helps developers write secure, performant database code.`;
|
|
261
|
+
const dataPayload = `**CODE WITH DATABASE QUERIES:**
|
|
262
|
+
|
|
263
|
+
\`\`\`${language}
|
|
264
|
+
${code}
|
|
265
|
+
\`\`\`
|
|
266
|
+
|
|
267
|
+
**EXTRACTED DATABASE QUERIES:**
|
|
268
|
+
${extractedQueries.length > 0 ?
|
|
269
|
+
extractedQueries.map((query, index) => `**Query ${index + 1}** (Line ${query.line}):\n\`\`\`sql\n${query.query}\n\`\`\`\nContext: ${query.context}\n`).join('\n') :
|
|
270
|
+
'No explicit database queries detected. Analyzing for potential query patterns and ORM usage.'}
|
|
271
|
+
|
|
272
|
+
${filePath ? `\n**File Path:** ${filePath}` : ''}`;
|
|
273
|
+
const outputInstructions = `**PROVIDE COMPREHENSIVE DATABASE QUERY ANALYSIS:**
|
|
274
|
+
|
|
275
|
+
## Executive Summary
|
|
276
|
+
Provide a 2-3 sentence overview of database usage, query patterns, and main security/performance concerns found in this file.
|
|
277
|
+
|
|
278
|
+
## Query Analysis Overview
|
|
279
|
+
- **Total Queries Found**: Count of database queries identified in the code
|
|
280
|
+
- **Query Types**: Breakdown of query types (SELECT, INSERT, UPDATE, DELETE, etc.)
|
|
281
|
+
- **Complex Queries**: Identification of complex queries that need attention
|
|
282
|
+
- **Dynamic Queries**: Queries built dynamically at runtime
|
|
283
|
+
|
|
284
|
+
## Security Analysis
|
|
285
|
+
For each security finding:
|
|
286
|
+
- **Vulnerability Type**: SQL injection, prepared statements, input validation, etc.
|
|
287
|
+
- **Severity Level**: Critical, high, medium, or low priority
|
|
288
|
+
- **Vulnerable Query**: The specific problematic query
|
|
289
|
+
- **Location**: Line number and context
|
|
290
|
+
- **Security Risk**: Detailed description of the security issue
|
|
291
|
+
- **Exploit Scenario**: How this vulnerability could be exploited
|
|
292
|
+
- **Fix Recommendation**: Specific fix with secure code example
|
|
293
|
+
- **Implementation**: Example of secure implementation
|
|
294
|
+
|
|
295
|
+
## Performance Analysis
|
|
296
|
+
For each performance issue:
|
|
297
|
+
- **Performance Problem**: N+1 queries, missing indexes, inefficient queries, excessive joins
|
|
298
|
+
- **Impact Level**: Critical, high, medium, or low performance impact
|
|
299
|
+
- **Problematic Query**: The query causing performance issues
|
|
300
|
+
- **Location**: Line number and context
|
|
301
|
+
"issue": "Detailed performance issue description",
|
|
302
|
+
"impact": "Performance impact (queries/second, memory usage)",
|
|
303
|
+
"optimization": "Specific optimization strategy",
|
|
304
|
+
"optimizedQuery": "Improved query example"
|
|
305
|
+
}
|
|
306
|
+
],
|
|
307
|
+
|
|
308
|
+
"bestPracticeViolations": [
|
|
309
|
+
{
|
|
310
|
+
"practice": "Best practice being violated",
|
|
311
|
+
"line": 78,
|
|
312
|
+
"current": "Current implementation",
|
|
313
|
+
"recommended": "Recommended implementation",
|
|
314
|
+
"benefit": "Why this improvement matters"
|
|
315
|
+
}
|
|
316
|
+
],
|
|
317
|
+
|
|
318
|
+
"recommendations": {
|
|
319
|
+
"immediate": [
|
|
320
|
+
"Critical security fix 1",
|
|
321
|
+
"Critical performance fix 1"
|
|
322
|
+
],
|
|
323
|
+
"shortTerm": [
|
|
324
|
+
"Performance optimization 1",
|
|
325
|
+
"Code quality improvement 1"
|
|
326
|
+
],
|
|
327
|
+
"longTerm": [
|
|
328
|
+
"Architectural improvement 1",
|
|
329
|
+
"Scalability enhancement 1"
|
|
330
|
+
]
|
|
331
|
+
},
|
|
332
|
+
|
|
333
|
+
"codeExamples": {
|
|
334
|
+
"before": "// Current problematic database code",
|
|
335
|
+
"after": "// Optimized and secure version",
|
|
336
|
+
"explanation": "Why this improvement enhances security and performance"
|
|
337
|
+
},
|
|
338
|
+
|
|
339
|
+
"indexRecommendations": [
|
|
340
|
+
{
|
|
341
|
+
"table": "table_name",
|
|
342
|
+
"columns": ["column1", "column2"],
|
|
343
|
+
"type": "btree|hash|partial",
|
|
344
|
+
"reasoning": "Why this index improves performance"
|
|
345
|
+
}
|
|
346
|
+
],
|
|
347
|
+
|
|
348
|
+
"metrics": {
|
|
349
|
+
"estimatedQueriesPerRequest": 5,
|
|
350
|
+
"potentialBottlenecks": 2,
|
|
351
|
+
"securityRiskLevel": "high|medium|low",
|
|
352
|
+
"optimizationPotential": "high|medium|low"
|
|
353
|
+
},
|
|
354
|
+
|
|
355
|
+
"confidence": 0.92
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
**CRITICAL REQUIREMENTS:**
|
|
359
|
+
- Focus on real, exploitable security vulnerabilities
|
|
360
|
+
- Provide specific query optimizations with measurable impact
|
|
361
|
+
- Include framework-specific best practices for ${framework}
|
|
362
|
+
- Consider ${database}-specific optimization techniques
|
|
363
|
+
- Prioritize fixes by impact and implementation difficulty`;
|
|
364
|
+
return { systemAndContext, dataPayload, outputInstructions };
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Multi-file database analysis for project-wide query patterns
|
|
368
|
+
*/
|
|
369
|
+
getMultiFilePromptStages(params) {
|
|
370
|
+
const { analysisResult, analysisType, analysisDepth, fileCount, context = {} } = params;
|
|
371
|
+
const database = context.database || 'generic';
|
|
372
|
+
const framework = context.framework || 'generic';
|
|
373
|
+
const systemAndContext = `You are a senior database architect specializing in ${analysisDepth} multi-file database analysis and optimization.
|
|
374
|
+
|
|
375
|
+
**PROJECT DATABASE ANALYSIS CONTEXT:**
|
|
376
|
+
- Database Engine: ${database}
|
|
377
|
+
- Framework: ${framework}
|
|
378
|
+
- Analysis Type: ${analysisType}
|
|
379
|
+
- Analysis Depth: ${analysisDepth}
|
|
380
|
+
- Files Analyzed: ${fileCount}
|
|
381
|
+
- Mode: Multi-File Database Architecture Analysis
|
|
382
|
+
|
|
383
|
+
**YOUR EXPERTISE:**
|
|
384
|
+
You excel at identifying cross-file database patterns, architectural issues, and system-wide database optimization opportunities. You understand how queries interact across modules, transaction boundaries, and data consistency patterns.
|
|
385
|
+
|
|
386
|
+
**FOCUS AREAS:**
|
|
387
|
+
- Cross-file query patterns and duplication
|
|
388
|
+
- Database transaction boundaries and consistency
|
|
389
|
+
- Query performance across the application
|
|
390
|
+
- Security patterns and vulnerabilities at scale
|
|
391
|
+
- Database schema utilization and optimization opportunities`;
|
|
392
|
+
const dataPayload = `**PROJECT DATABASE ANALYSIS RESULTS:**
|
|
393
|
+
|
|
394
|
+
${JSON.stringify(analysisResult, null, 2)}`;
|
|
395
|
+
const outputInstructions = `**PROVIDE PROJECT-WIDE DATABASE ANALYSIS:**
|
|
396
|
+
|
|
397
|
+
## Executive Summary
|
|
398
|
+
Overall assessment of database usage patterns, architecture quality, and system-wide security/performance concerns across the project.
|
|
399
|
+
|
|
400
|
+
## Database Architecture Analysis
|
|
401
|
+
- **Query Patterns**: Common patterns used throughout the project
|
|
402
|
+
- **Data Access Layers**: How database access is organized across files
|
|
403
|
+
- **Transaction Boundaries**: Transaction management patterns across the system
|
|
404
|
+
- **Consistency Approach**: Eventual, strong, or mixed consistency patterns
|
|
405
|
+
|
|
406
|
+
## Cross-File Analysis
|
|
407
|
+
For each system-wide issue identified:
|
|
408
|
+
- **Issue Type**: Query duplication, transaction issues, N+1 patterns, security patterns
|
|
409
|
+
- **Severity Impact**: Critical, high, medium, or low system impact
|
|
410
|
+
- **Issue Title**: Descriptive name for the cross-file issue
|
|
411
|
+
- **Description**: Detailed explanation of the system-wide problem
|
|
412
|
+
- **Affected Files**: List of files involved in this issue
|
|
413
|
+
- **System Impact**: How this affects overall performance/security
|
|
414
|
+
- **Resolution Strategy**: System-wide fix approach
|
|
415
|
+
|
|
416
|
+
## Performance Architecture
|
|
417
|
+
- **Query Distribution**: How database queries are distributed across the codebase
|
|
418
|
+
- **Bottleneck Patterns**: Common performance bottlenecks across files
|
|
419
|
+
- **Caching Strategy**: Current approach to database result caching
|
|
420
|
+
- **Optimization Opportunities**: System-wide performance improvements
|
|
421
|
+
|
|
422
|
+
## Security Architecture
|
|
423
|
+
- **Input Validation Patterns**: Consistency of input validation (consistent/inconsistent/missing)
|
|
424
|
+
- **Prepared Statement Usage**: Overall usage of prepared statements (high/medium/low)
|
|
425
|
+
- **Privilege Patterns**: Common privilege and access control patterns
|
|
426
|
+
- **High Risk Areas**: Areas requiring immediate security attention
|
|
427
|
+
|
|
428
|
+
## System-Wide Recommendations
|
|
429
|
+
- **Architecture Improvements**: Database architecture enhancements
|
|
430
|
+
- **Performance Optimizations**: System-wide performance improvements
|
|
431
|
+
- **Security Enhancements**: Security strengthening recommendations
|
|
432
|
+
- **Maintainability Improvements**: Long-term maintenance considerations
|
|
433
|
+
|
|
434
|
+
Focus on actionable recommendations that improve overall database architecture, performance, and security across the entire project.`;
|
|
435
|
+
return { systemAndContext, dataPayload, outputInstructions };
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Backwards compatibility method
|
|
439
|
+
*/
|
|
440
|
+
getPromptStages(params) {
|
|
441
|
+
const mode = this.detectAnalysisMode(params);
|
|
442
|
+
if (mode === 'single-file') {
|
|
443
|
+
return this.getSingleFilePromptStages(params);
|
|
444
|
+
}
|
|
445
|
+
else {
|
|
446
|
+
return this.getMultiFilePromptStages(params);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
// Multi-file helper methods
|
|
450
|
+
async discoverRelevantFiles(projectPath, maxDepth, analysisType) {
|
|
451
|
+
const extensions = this.getFileExtensions(analysisType);
|
|
452
|
+
return await this.multiFileAnalysis.discoverFiles(projectPath, extensions, maxDepth);
|
|
453
|
+
}
|
|
454
|
+
async performMultiFileAnalysis(files, params, model, contextLength) {
|
|
455
|
+
const cacheKey = this.analysisCache.generateKey('analyze_database_queries', params, files);
|
|
456
|
+
const cached = await this.analysisCache.get(cacheKey);
|
|
457
|
+
if (cached)
|
|
458
|
+
return cached;
|
|
459
|
+
const fileAnalysisResults = await this.multiFileAnalysis.analyzeBatch(files, (file) => this.analyzeIndividualFile(file, params, model), contextLength);
|
|
460
|
+
// Aggregate database-specific results
|
|
461
|
+
const aggregatedResult = {
|
|
462
|
+
summary: `Multi-file database analysis of ${files.length} files`,
|
|
463
|
+
findings: fileAnalysisResults,
|
|
464
|
+
database: this.analyzeDatabasePatterns(fileAnalysisResults),
|
|
465
|
+
queries: this.aggregateQueryAnalysis(fileAnalysisResults),
|
|
466
|
+
security: this.aggregateSecurityFindings(fileAnalysisResults),
|
|
467
|
+
performance: this.aggregatePerformanceFindings(fileAnalysisResults),
|
|
468
|
+
data: {
|
|
469
|
+
fileCount: files.length,
|
|
470
|
+
totalQueries: fileAnalysisResults.reduce((sum, result) => sum + (result.queryCount || 0), 0),
|
|
471
|
+
riskLevel: this.calculateRiskLevel(fileAnalysisResults),
|
|
472
|
+
frameworks: this.identifyDatabaseFrameworks(fileAnalysisResults)
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
await this.analysisCache.cacheAnalysis(cacheKey, aggregatedResult, {
|
|
476
|
+
modelUsed: model.identifier || 'unknown',
|
|
477
|
+
executionTime: Date.now(),
|
|
478
|
+
timestamp: new Date().toISOString()
|
|
479
|
+
});
|
|
480
|
+
return aggregatedResult;
|
|
481
|
+
}
|
|
482
|
+
async analyzeIndividualFile(file, params, model) {
|
|
483
|
+
const content = await readFile(file, 'utf-8');
|
|
484
|
+
const stats = await stat(file);
|
|
485
|
+
const queries = this.extractDatabaseQueries(content, params.language, params.context);
|
|
486
|
+
return {
|
|
487
|
+
filePath: file,
|
|
488
|
+
fileName: basename(file),
|
|
489
|
+
size: content.length,
|
|
490
|
+
lines: content.split('\n').length,
|
|
491
|
+
extension: extname(file),
|
|
492
|
+
relativePath: relative(params.projectPath || '', file),
|
|
493
|
+
// Database-specific analysis
|
|
494
|
+
queryCount: queries.length,
|
|
495
|
+
queries: queries,
|
|
496
|
+
databaseCalls: this.countDatabaseCalls(content),
|
|
497
|
+
securityRisks: this.identifySecurityRisks(queries),
|
|
498
|
+
performanceIssues: this.identifyPerformanceIssues(queries),
|
|
499
|
+
modified: stats.mtime
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Extract database queries from code using patterns for different languages/frameworks
|
|
504
|
+
*/
|
|
505
|
+
extractDatabaseQueries(code, language = 'php', context = {}) {
|
|
506
|
+
const queries = [];
|
|
507
|
+
const lines = code.split('\n');
|
|
508
|
+
// WordPress $wpdb patterns
|
|
509
|
+
const wpdbPatterns = [
|
|
510
|
+
/\$wpdb->query\s*\(\s*['"](.*?)['"].*?\)/gi,
|
|
511
|
+
/\$wpdb->get_results\s*\(\s*['"](.*?)['"].*?\)/gi,
|
|
512
|
+
/\$wpdb->get_var\s*\(\s*['"](.*?)['"].*?\)/gi,
|
|
513
|
+
/\$wpdb->get_row\s*\(\s*['"](.*?)['"].*?\)/gi,
|
|
514
|
+
/\$wpdb->prepare\s*\(\s*['"](.*?)['"].*?\)/gi
|
|
515
|
+
];
|
|
516
|
+
// Raw SQL patterns
|
|
517
|
+
const sqlPatterns = [
|
|
518
|
+
/(SELECT\s+.*?FROM\s+.*?)(?=;|\s*$|\s*\))/gis,
|
|
519
|
+
/(INSERT\s+INTO\s+.*?)(?=;|\s*$|\s*\))/gis,
|
|
520
|
+
/(UPDATE\s+.*?SET\s+.*?)(?=;|\s*$|\s*\))/gis,
|
|
521
|
+
/(DELETE\s+FROM\s+.*?)(?=;|\s*$|\s*\))/gis
|
|
522
|
+
];
|
|
523
|
+
// Laravel Eloquent patterns
|
|
524
|
+
const eloquentPatterns = [
|
|
525
|
+
/DB::select\s*\(\s*['"](.*?)['"].*?\)/gi,
|
|
526
|
+
/DB::insert\s*\(\s*['"](.*?)['"].*?\)/gi,
|
|
527
|
+
/DB::update\s*\(\s*['"](.*?)['"].*?\)/gi,
|
|
528
|
+
/DB::delete\s*\(\s*['"](.*?)['"].*?\)/gi
|
|
529
|
+
];
|
|
530
|
+
const patterns = [...wpdbPatterns, ...sqlPatterns, ...eloquentPatterns];
|
|
531
|
+
lines.forEach((line, index) => {
|
|
532
|
+
patterns.forEach(pattern => {
|
|
533
|
+
let match;
|
|
534
|
+
pattern.lastIndex = 0; // Reset regex
|
|
535
|
+
while ((match = pattern.exec(line)) !== null) {
|
|
536
|
+
queries.push({
|
|
537
|
+
query: match[1] || match[0],
|
|
538
|
+
line: index + 1,
|
|
539
|
+
context: this.getQueryContext(line),
|
|
540
|
+
type: this.getQueryType(match[1] || match[0]),
|
|
541
|
+
framework: this.detectQueryFramework(line)
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
});
|
|
546
|
+
return queries;
|
|
547
|
+
}
|
|
548
|
+
getQueryContext(line) {
|
|
549
|
+
if (line.includes('$wpdb'))
|
|
550
|
+
return 'WordPress';
|
|
551
|
+
if (line.includes('DB::'))
|
|
552
|
+
return 'Laravel';
|
|
553
|
+
if (line.includes('query(') || line.includes('execute('))
|
|
554
|
+
return 'Direct SQL';
|
|
555
|
+
return 'Unknown';
|
|
556
|
+
}
|
|
557
|
+
getQueryType(query) {
|
|
558
|
+
if (/^SELECT/i.test(query.trim()))
|
|
559
|
+
return 'SELECT';
|
|
560
|
+
if (/^INSERT/i.test(query.trim()))
|
|
561
|
+
return 'INSERT';
|
|
562
|
+
if (/^UPDATE/i.test(query.trim()))
|
|
563
|
+
return 'UPDATE';
|
|
564
|
+
if (/^DELETE/i.test(query.trim()))
|
|
565
|
+
return 'DELETE';
|
|
566
|
+
return 'OTHER';
|
|
567
|
+
}
|
|
568
|
+
detectQueryFramework(line) {
|
|
569
|
+
if (line.includes('$wpdb'))
|
|
570
|
+
return 'WordPress';
|
|
571
|
+
if (line.includes('DB::'))
|
|
572
|
+
return 'Laravel';
|
|
573
|
+
if (line.includes('PDO'))
|
|
574
|
+
return 'PDO';
|
|
575
|
+
return 'Generic';
|
|
576
|
+
}
|
|
577
|
+
countDatabaseCalls(content) {
|
|
578
|
+
const dbCallPatterns = [
|
|
579
|
+
/\$wpdb->/g,
|
|
580
|
+
/DB::/g,
|
|
581
|
+
/->query\(/g,
|
|
582
|
+
/->execute\(/g,
|
|
583
|
+
/mysqli_/g,
|
|
584
|
+
/pg_query/g
|
|
585
|
+
];
|
|
586
|
+
return dbCallPatterns.reduce((count, pattern) => {
|
|
587
|
+
const matches = content.match(pattern) || [];
|
|
588
|
+
return count + matches.length;
|
|
589
|
+
}, 0);
|
|
590
|
+
}
|
|
591
|
+
identifySecurityRisks(queries) {
|
|
592
|
+
const risks = [];
|
|
593
|
+
queries.forEach(query => {
|
|
594
|
+
// Check for potential SQL injection
|
|
595
|
+
if (query.query.includes('$') && !query.query.includes('prepare')) {
|
|
596
|
+
risks.push('Potential SQL injection vulnerability');
|
|
597
|
+
}
|
|
598
|
+
// Check for dynamic query construction
|
|
599
|
+
if (query.query.includes('{') || query.query.includes('}')) {
|
|
600
|
+
risks.push('Dynamic query construction detected');
|
|
601
|
+
}
|
|
602
|
+
// Check for missing prepared statements
|
|
603
|
+
if (query.framework === 'WordPress' && !query.context.includes('prepare')) {
|
|
604
|
+
risks.push('Unprepared WordPress query');
|
|
605
|
+
}
|
|
606
|
+
});
|
|
607
|
+
return [...new Set(risks)]; // Remove duplicates
|
|
608
|
+
}
|
|
609
|
+
identifyPerformanceIssues(queries) {
|
|
610
|
+
const issues = [];
|
|
611
|
+
queries.forEach(query => {
|
|
612
|
+
// Check for SELECT *
|
|
613
|
+
if (query.query.includes('SELECT *')) {
|
|
614
|
+
issues.push('SELECT * usage detected');
|
|
615
|
+
}
|
|
616
|
+
// Check for missing WHERE clauses in UPDATE/DELETE
|
|
617
|
+
if ((query.type === 'UPDATE' || query.type === 'DELETE') && !query.query.includes('WHERE')) {
|
|
618
|
+
issues.push('Missing WHERE clause in destructive operation');
|
|
619
|
+
}
|
|
620
|
+
// Check for potential N+1 queries (simple heuristic)
|
|
621
|
+
if (query.context.includes('foreach') || query.context.includes('for (')) {
|
|
622
|
+
issues.push('Potential N+1 query pattern');
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
return [...new Set(issues)];
|
|
626
|
+
}
|
|
627
|
+
// Database-specific aggregation methods
|
|
628
|
+
analyzeDatabasePatterns(results) {
|
|
629
|
+
return {
|
|
630
|
+
totalQueries: results.reduce((sum, r) => sum + (r.queryCount || 0), 0),
|
|
631
|
+
frameworks: this.identifyDatabaseFrameworks(results),
|
|
632
|
+
queryTypes: this.aggregateQueryTypes(results)
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
aggregateQueryAnalysis(results) {
|
|
636
|
+
const allQueries = results.flatMap(r => r.queries || []);
|
|
637
|
+
return {
|
|
638
|
+
total: allQueries.length,
|
|
639
|
+
byType: this.groupBy(allQueries, 'type'),
|
|
640
|
+
byFramework: this.groupBy(allQueries, 'framework')
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
aggregateSecurityFindings(results) {
|
|
644
|
+
const allRisks = results.flatMap(r => r.securityRisks || []);
|
|
645
|
+
return {
|
|
646
|
+
totalRisks: allRisks.length,
|
|
647
|
+
riskTypes: this.countOccurrences(allRisks)
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
aggregatePerformanceFindings(results) {
|
|
651
|
+
const allIssues = results.flatMap(r => r.performanceIssues || []);
|
|
652
|
+
return {
|
|
653
|
+
totalIssues: allIssues.length,
|
|
654
|
+
issueTypes: this.countOccurrences(allIssues)
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
calculateRiskLevel(results) {
|
|
658
|
+
const totalRisks = results.reduce((sum, r) => sum + (r.securityRisks?.length || 0), 0);
|
|
659
|
+
if (totalRisks > 10)
|
|
660
|
+
return 'high';
|
|
661
|
+
if (totalRisks > 5)
|
|
662
|
+
return 'medium';
|
|
663
|
+
return 'low';
|
|
664
|
+
}
|
|
665
|
+
identifyDatabaseFrameworks(results) {
|
|
666
|
+
const frameworks = new Set();
|
|
667
|
+
results.forEach(result => {
|
|
668
|
+
if (result.queries) {
|
|
669
|
+
result.queries.forEach((query) => {
|
|
670
|
+
frameworks.add(query.framework);
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
return Array.from(frameworks);
|
|
675
|
+
}
|
|
676
|
+
aggregateQueryTypes(results) {
|
|
677
|
+
const types = {};
|
|
678
|
+
results.forEach(result => {
|
|
679
|
+
if (result.queries) {
|
|
680
|
+
result.queries.forEach((query) => {
|
|
681
|
+
types[query.type] = (types[query.type] || 0) + 1;
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
return types;
|
|
686
|
+
}
|
|
687
|
+
groupBy(array, key) {
|
|
688
|
+
return array.reduce((groups, item) => {
|
|
689
|
+
const group = item[key] || 'unknown';
|
|
690
|
+
groups[group] = (groups[group] || 0) + 1;
|
|
691
|
+
return groups;
|
|
692
|
+
}, {});
|
|
693
|
+
}
|
|
694
|
+
countOccurrences(array) {
|
|
695
|
+
return array.reduce((counts, item) => {
|
|
696
|
+
counts[item] = (counts[item] || 0) + 1;
|
|
697
|
+
return counts;
|
|
698
|
+
}, {});
|
|
699
|
+
}
|
|
700
|
+
getFileExtensions(analysisType) {
|
|
701
|
+
const extensionMap = {
|
|
702
|
+
'security': ['.php', '.js', '.ts', '.py', '.rb', '.java', '.cs', '.sql'],
|
|
703
|
+
'performance': ['.php', '.js', '.ts', '.py', '.rb', '.java', '.cs', '.sql'],
|
|
704
|
+
'best-practices': ['.php', '.js', '.ts', '.py', '.rb', '.java', '.cs', '.sql'],
|
|
705
|
+
'comprehensive': ['.php', '.js', '.ts', '.py', '.rb', '.java', '.cs', '.sql', '.jsp', '.asp', '.aspx']
|
|
706
|
+
};
|
|
707
|
+
return extensionMap[analysisType] || extensionMap.comprehensive;
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* Database and framework-specific expert instructions
|
|
711
|
+
*/
|
|
712
|
+
getDatabaseSpecificInstructions(database, framework, orm) {
|
|
713
|
+
const instructions = {
|
|
714
|
+
'wordpress': `
|
|
715
|
+
**WORDPRESS DATABASE EXPERTISE:**
|
|
716
|
+
- $wpdb best practices: Always use $wpdb->prepare() for dynamic queries
|
|
717
|
+
- WordPress query functions: get_results(), get_var(), get_row(), get_col()
|
|
718
|
+
- Custom table naming: Use $wpdb->prefix for table prefixes
|
|
719
|
+
- Caching integration: wp_cache_* functions for query result caching
|
|
720
|
+
- Security: Validate and sanitize all input, use wpdb::esc_like() for LIKE queries
|
|
721
|
+
- Performance: Avoid queries in loops, use WP_Query efficiently, leverage object caching
|
|
722
|
+
- Schema: Follow WordPress database schema conventions, use dbDelta() for table creation`,
|
|
723
|
+
'laravel': `
|
|
724
|
+
**LARAVEL DATABASE EXPERTISE:**
|
|
725
|
+
- Eloquent ORM: Use relationships to avoid N+1 queries, eager loading with with()
|
|
726
|
+
- Query Builder: DB::table() with proper parameter binding
|
|
727
|
+
- Raw queries: Always use DB::select() with parameter binding, never string concatenation
|
|
728
|
+
- Migrations: Use Schema builder for database changes, maintain rollback capability
|
|
729
|
+
- Performance: Query scopes, database indexes, query caching with Redis/Memcached
|
|
730
|
+
- Security: Always use parameter binding, validate inputs with Form Requests
|
|
731
|
+
- Transactions: Use DB::transaction() for data consistency`,
|
|
732
|
+
'django': `
|
|
733
|
+
**DJANGO DATABASE EXPERTISE:**
|
|
734
|
+
- ORM QuerySets: Use select_related() and prefetch_related() to minimize queries
|
|
735
|
+
- Raw SQL: Always use parameterized queries, never string formatting
|
|
736
|
+
- Migrations: Use Django migrations for schema changes
|
|
737
|
+
- Performance: Database indexes, QuerySet optimization, database connection pooling
|
|
738
|
+
- Security: Django ORM provides SQL injection protection by default
|
|
739
|
+
- Caching: Use Django's cache framework for query result caching`,
|
|
740
|
+
'generic': `
|
|
741
|
+
**GENERAL DATABASE EXPERTISE:**
|
|
742
|
+
- Always use prepared statements or parameterized queries
|
|
743
|
+
- Validate and sanitize all user inputs before database operations
|
|
744
|
+
- Use appropriate indexes for query performance
|
|
745
|
+
- Avoid SELECT * and fetch only required columns
|
|
746
|
+
- Implement proper error handling and logging
|
|
747
|
+
- Use transactions for data consistency
|
|
748
|
+
- Consider connection pooling for high-traffic applications`
|
|
749
|
+
};
|
|
750
|
+
return instructions[framework] || instructions[database] || instructions.generic;
|
|
751
|
+
}
|
|
752
|
+
generateCacheKey(files, params) {
|
|
753
|
+
const fileHash = files.join('|');
|
|
754
|
+
const paramHash = JSON.stringify(params);
|
|
755
|
+
return `${fileHash}_${paramHash}`.substring(0, 64);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
export default DatabaseQueryAnalyzer;
|
|
759
|
+
//# sourceMappingURL=database-queries.js.map
|