noormme 1.1.0 → 1.2.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/README.md +84 -65
- package/dist/cjs/agentic/ActionJournal.js +13 -9
- package/dist/cjs/agentic/CapabilityManager.js +35 -21
- package/dist/cjs/agentic/CognitiveRepository.js +19 -9
- package/dist/cjs/agentic/ContextBuffer.js +24 -12
- package/dist/cjs/agentic/Cortex.js +11 -4
- package/dist/cjs/agentic/EpisodicMemory.js +7 -5
- package/dist/cjs/agentic/PersonaManager.js +16 -8
- package/dist/cjs/agentic/PolicyEnforcer.js +31 -12
- package/dist/cjs/agentic/ResourceMonitor.js +4 -4
- package/dist/cjs/agentic/SessionCompressor.js +22 -14
- package/dist/cjs/agentic/SessionManager.js +36 -18
- package/dist/cjs/agentic/VectorIndexer.js +22 -18
- package/dist/cjs/agentic/improvement/AblationEngine.js +22 -15
- package/dist/cjs/agentic/improvement/ActionRefiner.js +12 -10
- package/dist/cjs/agentic/improvement/ConflictResolver.js +5 -5
- package/dist/cjs/agentic/improvement/CortexJanitor.js +30 -9
- package/dist/cjs/agentic/improvement/CuriosityEngine.js +27 -23
- package/dist/cjs/agentic/improvement/EvolutionRitual.js +4 -4
- package/dist/cjs/agentic/improvement/EvolutionaryPilot.js +16 -6
- package/dist/cjs/agentic/improvement/GoalArchitect.d.ts +2 -2
- package/dist/cjs/agentic/improvement/GoalArchitect.js +20 -18
- package/dist/cjs/agentic/improvement/GovernanceManager.js +19 -11
- package/dist/cjs/agentic/improvement/HiveLink.js +22 -15
- package/dist/cjs/agentic/improvement/KnowledgeDistiller.js +48 -32
- package/dist/cjs/agentic/improvement/RecursiveReasoner.js +40 -17
- package/dist/cjs/agentic/improvement/ReflectionEngine.js +10 -8
- package/dist/cjs/agentic/improvement/RitualOrchestrator.js +28 -22
- package/dist/cjs/agentic/improvement/RuleEngine.js +22 -17
- package/dist/cjs/agentic/improvement/SelfEvolution.js +24 -18
- package/dist/cjs/agentic/improvement/SelfTestRegistry.js +18 -15
- package/dist/cjs/agentic/improvement/SkillSynthesizer.js +42 -27
- package/dist/cjs/agentic/improvement/SovereignMetrics.js +19 -17
- package/dist/cjs/agentic/improvement/StrategicPlanner.js +120 -55
- package/dist/cjs/agentic/telemetry/CognitiveSynthesizer.js +26 -12
- package/dist/cjs/agentic/telemetry/EventHarvester.js +3 -2
- package/dist/cjs/agentic/telemetry/ResearchAlchemist.js +5 -2
- package/dist/cjs/cache/cache-manager.js +7 -4
- package/dist/cjs/cli/commands/analyze.js +5 -4
- package/dist/cjs/cli/commands/generate.js +81 -44
- package/dist/cjs/cli/commands/init.js +7 -3
- package/dist/cjs/cli/commands/inspect.js +139 -36
- package/dist/cjs/cli/commands/migrate.js +5 -4
- package/dist/cjs/cli/commands/optimize.js +4 -4
- package/dist/cjs/cli/commands/status.js +9 -7
- package/dist/cjs/cli/commands/watch.js +7 -6
- package/dist/cjs/cli/index.js +2 -2
- package/dist/cjs/cli/ui/spinner.d.ts +15 -0
- package/dist/cjs/cli/ui/spinner.js +76 -0
- package/dist/cjs/dialect/database-introspector.js +3 -1
- package/dist/cjs/dialect/postgresql/postgresql-driver.js +3 -1
- package/dist/cjs/dialect/postgresql/postgresql-features.js +18 -8
- package/dist/cjs/dialect/postgresql/postgresql-introspector.js +2 -2
- package/dist/cjs/dialect/sqlite/sqlite-auto-indexer.js +47 -33
- package/dist/cjs/dialect/sqlite/sqlite-auto-optimizer.js +8 -7
- package/dist/cjs/dialect/sqlite/sqlite-driver.js +2 -2
- package/dist/cjs/dialect/sqlite/sqlite-introspector.js +15 -12
- package/dist/cjs/edge-runtime/edge-config.js +21 -19
- package/dist/cjs/errors/NoormError.js +22 -20
- package/dist/cjs/helpers/agent-schema.js +2 -0
- package/dist/cjs/helpers/postgresql.js +7 -4
- package/dist/cjs/helpers/schema-evolution.js +31 -6
- package/dist/cjs/index.d.ts +3 -3
- package/dist/cjs/logging/logger.js +8 -4
- package/dist/cjs/migration/data_migrator.js +12 -11
- package/dist/cjs/migration/database_migration_manager.js +17 -13
- package/dist/cjs/migration/schema_differ.js +22 -14
- package/dist/cjs/migration/schema_introspector.js +8 -8
- package/dist/cjs/migration/type_mapper.js +68 -67
- package/dist/cjs/noormme.js +52 -37
- package/dist/cjs/performance/index.js +5 -5
- package/dist/cjs/performance/query-optimizer.js +26 -21
- package/dist/cjs/performance/services/cache-service.js +26 -16
- package/dist/cjs/performance/services/connection-factory.js +28 -23
- package/dist/cjs/performance/services/metrics-collector.js +41 -36
- package/dist/cjs/performance/utils/query-parser.js +15 -16
- package/dist/cjs/relationships/relationship-engine.js +10 -8
- package/dist/cjs/repository/repository-factory.js +97 -38
- package/dist/cjs/schema/core/coordinators/schema-discovery.coordinator.js +1 -3
- package/dist/cjs/schema/core/discovery/relationship-discovery.js +16 -16
- package/dist/cjs/schema/core/discovery/table-metadata-discovery.js +9 -9
- package/dist/cjs/schema/core/discovery/view-discovery.js +5 -4
- package/dist/cjs/schema/core/factories/discovery-factory.js +4 -4
- package/dist/cjs/schema/core/utils/name-generator.js +14 -5
- package/dist/cjs/schema/core/utils/type-mapper.js +24 -24
- package/dist/cjs/schema/dialects/postgresql/postgresql-discovery.coordinator.js +8 -7
- package/dist/cjs/schema/dialects/sqlite/discovery/sqlite-constraint-discovery.js +17 -15
- package/dist/cjs/schema/dialects/sqlite/discovery/sqlite-index-discovery.js +8 -8
- package/dist/cjs/schema/dialects/sqlite/introspection/sqlite-schema-introspector.js +6 -11
- package/dist/cjs/schema/dialects/sqlite/sqlite-discovery.coordinator.js +14 -13
- package/dist/cjs/schema/test/basic-schema-test.js +11 -9
- package/dist/cjs/schema/test/dialect-capabilities.test.js +6 -6
- package/dist/cjs/schema/test/discovery-factory.test.js +2 -2
- package/dist/cjs/schema/test/error-handling.test.js +8 -6
- package/dist/cjs/schema/test/integration.test.js +24 -18
- package/dist/cjs/schema/test/schema-discovery-coordinator.test.js +9 -9
- package/dist/cjs/schema/test/simple-schema-test.js +9 -9
- package/dist/cjs/schema/test/sqlite-discovery-coordinator.test.js +64 -48
- package/dist/cjs/schema/test/test-runner.js +3 -3
- package/dist/cjs/sqlite-migration/index.d.ts +2 -2
- package/dist/cjs/sqlite-migration/sqlite-migration-manager.js +21 -17
- package/dist/cjs/sqlite-migration/sqlite-migration-provider.js +38 -34
- package/dist/cjs/testing/test-utils.js +36 -34
- package/dist/cjs/types/index.d.ts +5 -2
- package/dist/cjs/types/index.js +6 -3
- package/dist/cjs/types/type-generator.js +46 -42
- package/dist/cjs/util/safe-sql-helpers.js +1 -1
- package/dist/cjs/util/security-validator.js +20 -9
- package/dist/cjs/utils/errorHelpers.js +20 -10
- package/dist/cjs/watch/schema-watcher.js +22 -23
- package/dist/esm/agentic/ActionJournal.js +13 -9
- package/dist/esm/agentic/CapabilityManager.js +35 -21
- package/dist/esm/agentic/CognitiveRepository.js +19 -9
- package/dist/esm/agentic/ContextBuffer.js +24 -12
- package/dist/esm/agentic/Cortex.js +11 -4
- package/dist/esm/agentic/EpisodicMemory.js +7 -5
- package/dist/esm/agentic/PersonaManager.js +16 -8
- package/dist/esm/agentic/PolicyEnforcer.js +31 -12
- package/dist/esm/agentic/ResourceMonitor.js +4 -4
- package/dist/esm/agentic/SessionCompressor.js +22 -14
- package/dist/esm/agentic/SessionManager.js +36 -18
- package/dist/esm/agentic/VectorIndexer.js +22 -18
- package/dist/esm/agentic/improvement/AblationEngine.js +22 -15
- package/dist/esm/agentic/improvement/ActionRefiner.js +12 -10
- package/dist/esm/agentic/improvement/ConflictResolver.js +5 -5
- package/dist/esm/agentic/improvement/CortexJanitor.js +30 -9
- package/dist/esm/agentic/improvement/CuriosityEngine.js +27 -23
- package/dist/esm/agentic/improvement/EvolutionRitual.js +4 -4
- package/dist/esm/agentic/improvement/EvolutionaryPilot.js +16 -6
- package/dist/esm/agentic/improvement/GoalArchitect.d.ts +2 -2
- package/dist/esm/agentic/improvement/GoalArchitect.js +20 -18
- package/dist/esm/agentic/improvement/GovernanceManager.js +19 -11
- package/dist/esm/agentic/improvement/HiveLink.js +22 -15
- package/dist/esm/agentic/improvement/KnowledgeDistiller.js +48 -32
- package/dist/esm/agentic/improvement/RecursiveReasoner.js +40 -17
- package/dist/esm/agentic/improvement/ReflectionEngine.js +10 -8
- package/dist/esm/agentic/improvement/RitualOrchestrator.js +28 -22
- package/dist/esm/agentic/improvement/RuleEngine.js +22 -17
- package/dist/esm/agentic/improvement/SelfEvolution.js +24 -18
- package/dist/esm/agentic/improvement/SelfTestRegistry.js +18 -15
- package/dist/esm/agentic/improvement/SkillSynthesizer.js +42 -27
- package/dist/esm/agentic/improvement/SovereignMetrics.js +19 -17
- package/dist/esm/agentic/improvement/StrategicPlanner.js +120 -55
- package/dist/esm/agentic/telemetry/CognitiveSynthesizer.js +26 -12
- package/dist/esm/agentic/telemetry/EventHarvester.js +3 -2
- package/dist/esm/agentic/telemetry/ResearchAlchemist.js +5 -2
- package/dist/esm/cache/cache-manager.js +7 -4
- package/dist/esm/cli/commands/analyze.js +5 -4
- package/dist/esm/cli/commands/generate.js +82 -45
- package/dist/esm/cli/commands/init.js +8 -4
- package/dist/esm/cli/commands/inspect.js +140 -37
- package/dist/esm/cli/commands/migrate.js +5 -4
- package/dist/esm/cli/commands/optimize.js +4 -4
- package/dist/esm/cli/commands/status.js +9 -7
- package/dist/esm/cli/commands/watch.js +7 -6
- package/dist/esm/cli/index.js +2 -2
- package/dist/esm/cli/ui/spinner.d.ts +15 -0
- package/dist/esm/cli/ui/spinner.js +70 -0
- package/dist/esm/dialect/database-introspector.js +3 -1
- package/dist/esm/dialect/postgresql/postgresql-driver.js +3 -1
- package/dist/esm/dialect/postgresql/postgresql-features.js +18 -8
- package/dist/esm/dialect/postgresql/postgresql-introspector.js +2 -2
- package/dist/esm/dialect/sqlite/sqlite-auto-indexer.js +47 -33
- package/dist/esm/dialect/sqlite/sqlite-auto-optimizer.js +8 -7
- package/dist/esm/dialect/sqlite/sqlite-driver.js +2 -2
- package/dist/esm/dialect/sqlite/sqlite-introspector.js +15 -12
- package/dist/esm/dynamic/dynamic.js +1 -1
- package/dist/esm/edge-runtime/edge-config.js +21 -19
- package/dist/esm/errors/NoormError.js +22 -20
- package/dist/esm/helpers/agent-schema.js +2 -0
- package/dist/esm/helpers/postgresql.js +7 -4
- package/dist/esm/helpers/schema-evolution.js +31 -6
- package/dist/esm/index.d.ts +3 -3
- package/dist/esm/index.js +2 -2
- package/dist/esm/logging/logger.js +8 -4
- package/dist/esm/migration/data_migrator.js +12 -11
- package/dist/esm/migration/database_migration_manager.js +18 -14
- package/dist/esm/migration/schema_differ.js +22 -14
- package/dist/esm/migration/schema_introspector.js +8 -8
- package/dist/esm/migration/type_mapper.js +68 -67
- package/dist/esm/noormme.js +52 -37
- package/dist/esm/performance/index.js +5 -5
- package/dist/esm/performance/query-optimizer.js +26 -21
- package/dist/esm/performance/services/cache-service.js +26 -16
- package/dist/esm/performance/services/connection-factory.js +28 -23
- package/dist/esm/performance/services/metrics-collector.js +41 -36
- package/dist/esm/performance/utils/query-parser.js +15 -16
- package/dist/esm/raw-builder/sql.js +1 -1
- package/dist/esm/relationships/relationship-engine.js +10 -8
- package/dist/esm/repository/repository-factory.js +98 -39
- package/dist/esm/schema/builders/alter-table-add-index-builder.js +1 -1
- package/dist/esm/schema/builders/create-index-builder.js +2 -2
- package/dist/esm/schema/core/coordinators/schema-discovery.coordinator.js +1 -3
- package/dist/esm/schema/core/discovery/relationship-discovery.js +16 -16
- package/dist/esm/schema/core/discovery/table-metadata-discovery.js +9 -9
- package/dist/esm/schema/core/discovery/view-discovery.js +5 -4
- package/dist/esm/schema/core/factories/discovery-factory.js +4 -4
- package/dist/esm/schema/core/utils/name-generator.js +14 -5
- package/dist/esm/schema/core/utils/type-mapper.js +24 -24
- package/dist/esm/schema/dialects/postgresql/postgresql-discovery.coordinator.js +8 -7
- package/dist/esm/schema/dialects/sqlite/discovery/sqlite-constraint-discovery.js +17 -15
- package/dist/esm/schema/dialects/sqlite/discovery/sqlite-index-discovery.js +8 -8
- package/dist/esm/schema/dialects/sqlite/introspection/sqlite-schema-introspector.js +6 -11
- package/dist/esm/schema/dialects/sqlite/sqlite-discovery.coordinator.js +14 -13
- package/dist/esm/schema/test/basic-schema-test.js +11 -9
- package/dist/esm/schema/test/dialect-capabilities.test.js +6 -6
- package/dist/esm/schema/test/discovery-factory.test.js +2 -2
- package/dist/esm/schema/test/error-handling.test.js +8 -6
- package/dist/esm/schema/test/integration.test.js +24 -18
- package/dist/esm/schema/test/schema-discovery-coordinator.test.js +9 -9
- package/dist/esm/schema/test/simple-schema-test.js +9 -9
- package/dist/esm/schema/test/sqlite-discovery-coordinator.test.js +64 -48
- package/dist/esm/schema/test/test-runner.js +3 -3
- package/dist/esm/sqlite-migration/index.d.ts +2 -2
- package/dist/esm/sqlite-migration/sqlite-migration-manager.js +21 -17
- package/dist/esm/sqlite-migration/sqlite-migration-provider.js +38 -34
- package/dist/esm/testing/test-utils.js +36 -34
- package/dist/esm/types/index.d.ts +5 -2
- package/dist/esm/types/index.js +6 -3
- package/dist/esm/types/type-generator.js +46 -42
- package/dist/esm/util/safe-sql-helpers.js +1 -1
- package/dist/esm/util/security-validator.js +20 -9
- package/dist/esm/utils/errorHelpers.js +21 -11
- package/dist/esm/watch/schema-watcher.js +22 -23
- package/package.json +40 -44
|
@@ -18,11 +18,11 @@ async function optimize(options) {
|
|
|
18
18
|
host: 'localhost',
|
|
19
19
|
port: 0,
|
|
20
20
|
username: '',
|
|
21
|
-
password: ''
|
|
21
|
+
password: '',
|
|
22
22
|
},
|
|
23
23
|
performance: {
|
|
24
|
-
enableQueryOptimization: true
|
|
25
|
-
}
|
|
24
|
+
enableQueryOptimization: true,
|
|
25
|
+
},
|
|
26
26
|
});
|
|
27
27
|
await db.initialize();
|
|
28
28
|
console.log(chalk_1.default.gray(`📁 Database: ${databasePath}`));
|
|
@@ -106,7 +106,7 @@ async function optimize(options) {
|
|
|
106
106
|
console.log(chalk_1.default.gray('Would enable WAL mode for better concurrency'));
|
|
107
107
|
}
|
|
108
108
|
else {
|
|
109
|
-
const result = await db.execute('PRAGMA journal_mode = WAL');
|
|
109
|
+
const result = (await db.execute('PRAGMA journal_mode = WAL'));
|
|
110
110
|
let mode = 'unknown';
|
|
111
111
|
if (Array.isArray(result) && result.length > 0) {
|
|
112
112
|
mode = result[0].journal_mode;
|
|
@@ -54,11 +54,11 @@ async function status(options) {
|
|
|
54
54
|
host: 'localhost',
|
|
55
55
|
port: 0,
|
|
56
56
|
username: '',
|
|
57
|
-
password: ''
|
|
57
|
+
password: '',
|
|
58
58
|
},
|
|
59
59
|
performance: {
|
|
60
|
-
enableQueryOptimization: true
|
|
61
|
-
}
|
|
60
|
+
enableQueryOptimization: true,
|
|
61
|
+
},
|
|
62
62
|
});
|
|
63
63
|
await db.initialize();
|
|
64
64
|
console.log(chalk_1.default.gray(`📁 Database: ${databasePath}\n`));
|
|
@@ -113,7 +113,7 @@ async function status(options) {
|
|
|
113
113
|
console.log(chalk_1.default.gray(` Free pages: ${metrics.freePages.toLocaleString()}`));
|
|
114
114
|
if (scoreFactors.length > 0) {
|
|
115
115
|
console.log(chalk_1.default.green(`\n ✅ Performance factors:`));
|
|
116
|
-
scoreFactors.forEach(factor => {
|
|
116
|
+
scoreFactors.forEach((factor) => {
|
|
117
117
|
console.log(chalk_1.default.gray(` • ${factor}`));
|
|
118
118
|
});
|
|
119
119
|
}
|
|
@@ -175,7 +175,9 @@ async function status(options) {
|
|
|
175
175
|
const indexRecs = await db.getSQLiteIndexRecommendations();
|
|
176
176
|
if (indexRecs.recommendations.length > 0) {
|
|
177
177
|
console.log(chalk_1.default.yellow(` 📊 ${indexRecs.recommendations.length} recommendations available:`));
|
|
178
|
-
indexRecs.recommendations
|
|
178
|
+
indexRecs.recommendations
|
|
179
|
+
.slice(0, 5)
|
|
180
|
+
.forEach((rec, index) => {
|
|
179
181
|
console.log(chalk_1.default.gray(` ${index + 1}. ${rec.table}.${rec.column} - ${rec.reason}`));
|
|
180
182
|
});
|
|
181
183
|
if (indexRecs.recommendations.length > 5) {
|
|
@@ -264,7 +266,7 @@ async function getAutomationStatus(db) {
|
|
|
264
266
|
autoOptimization: config.automation?.enableAutoOptimization ?? true,
|
|
265
267
|
queryAnalysis: config.performance?.enableQueryOptimization ?? true,
|
|
266
268
|
autoIndexing: config.automation?.enableIndexRecommendations ?? true,
|
|
267
|
-
schemaMonitoring: config.automation?.enableSchemaWatcher ?? false
|
|
269
|
+
schemaMonitoring: config.automation?.enableSchemaWatcher ?? false,
|
|
268
270
|
};
|
|
269
271
|
}
|
|
270
272
|
catch {
|
|
@@ -272,7 +274,7 @@ async function getAutomationStatus(db) {
|
|
|
272
274
|
autoOptimization: true,
|
|
273
275
|
queryAnalysis: true,
|
|
274
276
|
autoIndexing: true,
|
|
275
|
-
schemaMonitoring: false
|
|
277
|
+
schemaMonitoring: false,
|
|
276
278
|
};
|
|
277
279
|
}
|
|
278
280
|
}
|
|
@@ -53,11 +53,11 @@ async function watch(options) {
|
|
|
53
53
|
host: 'localhost',
|
|
54
54
|
port: 0,
|
|
55
55
|
username: '',
|
|
56
|
-
password: ''
|
|
56
|
+
password: '',
|
|
57
57
|
},
|
|
58
58
|
performance: {
|
|
59
|
-
enableQueryOptimization: true
|
|
60
|
-
}
|
|
59
|
+
enableQueryOptimization: true,
|
|
60
|
+
},
|
|
61
61
|
});
|
|
62
62
|
await db.initialize();
|
|
63
63
|
const intervalMs = parseInt(options.interval || '5000');
|
|
@@ -76,7 +76,7 @@ async function watch(options) {
|
|
|
76
76
|
db.onSchemaChange(async (changes) => {
|
|
77
77
|
console.log(chalk_1.default.blue(`\n🔄 Schema changes detected at ${new Date().toLocaleTimeString()}`));
|
|
78
78
|
console.log(chalk_1.default.yellow('📊 Changes detected:'));
|
|
79
|
-
changes.forEach(change => {
|
|
79
|
+
changes.forEach((change) => {
|
|
80
80
|
let msg = ` • ${change.type}: ${change.table}`;
|
|
81
81
|
if (change.column)
|
|
82
82
|
msg += `.${change.column}`;
|
|
@@ -120,12 +120,13 @@ async function watch(options) {
|
|
|
120
120
|
// Start watching
|
|
121
121
|
await db.startSchemaWatching({
|
|
122
122
|
pollInterval: intervalMs,
|
|
123
|
-
enabled: true
|
|
123
|
+
enabled: true,
|
|
124
124
|
});
|
|
125
125
|
// Periodic tasks loop
|
|
126
126
|
const periodicTaskInterval = setInterval(async () => {
|
|
127
127
|
// Periodic optimization if auto-optimize is enabled
|
|
128
|
-
if (autoOptimize &&
|
|
128
|
+
if (autoOptimize &&
|
|
129
|
+
Date.now() - lastOptimizationTime > optimizationInterval) {
|
|
129
130
|
console.log(chalk_1.default.blue(`\n🔄 Periodic optimization check at ${new Date().toLocaleTimeString()}`));
|
|
130
131
|
try {
|
|
131
132
|
const metrics = await db.getSQLitePerformanceMetrics();
|
package/dist/cjs/cli/index.js
CHANGED
|
@@ -142,7 +142,7 @@ ${chalk_1.default.blue('📚 Learn more: https://github.com/noormme/noormme')}
|
|
|
142
142
|
`);
|
|
143
143
|
// Error handling
|
|
144
144
|
program.configureOutput({
|
|
145
|
-
writeErr: (str) => process.stderr.write(chalk_1.default.red(str))
|
|
145
|
+
writeErr: (str) => process.stderr.write(chalk_1.default.red(str)),
|
|
146
146
|
});
|
|
147
147
|
// Handle unknown commands
|
|
148
148
|
program.on('command:*', function (operands) {
|
|
@@ -155,6 +155,6 @@ program.parse();
|
|
|
155
155
|
// Show help if no command provided
|
|
156
156
|
if (!process.argv.slice(2).length) {
|
|
157
157
|
console.log(chalk_1.default.blue.bold('\n🎯 NOORMME - Automating SQLite with Intelligence\n'));
|
|
158
|
-
console.log(chalk_1.default.gray(
|
|
158
|
+
console.log(chalk_1.default.gray("The only SQLite ORM that automates everything. Built on Kysely's type-safe foundation.\n"));
|
|
159
159
|
program.outputHelp();
|
|
160
160
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const AGENTIC_LOADING_MESSAGES: string[];
|
|
2
|
+
export declare class AgenticSpinner {
|
|
3
|
+
private frames;
|
|
4
|
+
private currentFrame;
|
|
5
|
+
private currentMessageIdx;
|
|
6
|
+
private interval;
|
|
7
|
+
private messageInterval;
|
|
8
|
+
private baseMessage;
|
|
9
|
+
constructor(message?: string);
|
|
10
|
+
start(message?: string): void;
|
|
11
|
+
stop(): void;
|
|
12
|
+
succeed(message: string): void;
|
|
13
|
+
fail(message: string): void;
|
|
14
|
+
info(message: string): void;
|
|
15
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.AgenticSpinner = exports.AGENTIC_LOADING_MESSAGES = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
exports.AGENTIC_LOADING_MESSAGES = [
|
|
9
|
+
'Asking the LLM nicely to parse your terrible schema...',
|
|
10
|
+
'Downloading more agentic RAM from the dark web...',
|
|
11
|
+
'Bribing autonomous agents with virtual cookies...',
|
|
12
|
+
'Explaining SQL to the AI (it thinks JOIN is a cult)...',
|
|
13
|
+
'Reticulating cognitive splines with a rusty spoon...',
|
|
14
|
+
'Applying sovereign governance (begging the database to work)...',
|
|
15
|
+
'Waking up the Cortex nodes (they have a hangover)...',
|
|
16
|
+
'Synthesizing cognitive pathways (mashing keyboard)...',
|
|
17
|
+
'Pre-warming neural schemas with a slightly damp towel...',
|
|
18
|
+
'Aligning telemetry with your impending doom...',
|
|
19
|
+
'Teaching the AI what love is (it refused)...',
|
|
20
|
+
'Translating your code into something logically coherent...',
|
|
21
|
+
'Frantically Googling "how to ORM in TypeScript"...',
|
|
22
|
+
'Consulting the magic 8 ball for query optimization...'
|
|
23
|
+
];
|
|
24
|
+
class AgenticSpinner {
|
|
25
|
+
frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
26
|
+
currentFrame = 0;
|
|
27
|
+
currentMessageIdx = 0;
|
|
28
|
+
interval = null;
|
|
29
|
+
messageInterval = 0;
|
|
30
|
+
baseMessage = '';
|
|
31
|
+
constructor(message = '') {
|
|
32
|
+
this.baseMessage = message;
|
|
33
|
+
// Start with a random message to feel organic
|
|
34
|
+
this.currentMessageIdx = Math.floor(Math.random() * exports.AGENTIC_LOADING_MESSAGES.length);
|
|
35
|
+
}
|
|
36
|
+
start(message) {
|
|
37
|
+
if (message)
|
|
38
|
+
this.baseMessage = message;
|
|
39
|
+
if (this.interval)
|
|
40
|
+
return;
|
|
41
|
+
this.interval = setInterval(() => {
|
|
42
|
+
this.currentFrame = (this.currentFrame + 1) % this.frames.length;
|
|
43
|
+
this.messageInterval++;
|
|
44
|
+
// Rotate inner message every ~20 frames (2 seconds at 100ms/frame)
|
|
45
|
+
if (this.messageInterval > 20) {
|
|
46
|
+
this.messageInterval = 0;
|
|
47
|
+
this.currentMessageIdx = (this.currentMessageIdx + 1) % exports.AGENTIC_LOADING_MESSAGES.length;
|
|
48
|
+
}
|
|
49
|
+
const frame = chalk_1.default.cyan(this.frames[this.currentFrame]);
|
|
50
|
+
const agenticTone = chalk_1.default.gray(exports.AGENTIC_LOADING_MESSAGES[this.currentMessageIdx]);
|
|
51
|
+
const primaryText = this.baseMessage ? chalk_1.default.white(this.baseMessage) + ' - ' : '';
|
|
52
|
+
// Clear line and write new frame
|
|
53
|
+
process.stdout.write(`\r\x1b[K${frame} ${primaryText}${agenticTone} `);
|
|
54
|
+
}, 100);
|
|
55
|
+
}
|
|
56
|
+
stop() {
|
|
57
|
+
if (this.interval) {
|
|
58
|
+
clearInterval(this.interval);
|
|
59
|
+
this.interval = null;
|
|
60
|
+
}
|
|
61
|
+
process.stdout.write('\r\x1b[K');
|
|
62
|
+
}
|
|
63
|
+
succeed(message) {
|
|
64
|
+
this.stop();
|
|
65
|
+
console.log(`✅ ${chalk_1.default.green(message)} `);
|
|
66
|
+
}
|
|
67
|
+
fail(message) {
|
|
68
|
+
this.stop();
|
|
69
|
+
console.log(`❌ ${chalk_1.default.red(message)} `);
|
|
70
|
+
}
|
|
71
|
+
info(message) {
|
|
72
|
+
this.stop();
|
|
73
|
+
console.log(`ℹ️ ${chalk_1.default.blue(message)} `);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.AgenticSpinner = AgenticSpinner;
|
|
@@ -42,7 +42,9 @@ class DatabaseIntrospector {
|
|
|
42
42
|
`.execute(this.db);
|
|
43
43
|
const tables = [];
|
|
44
44
|
for (const row of result.rows) {
|
|
45
|
-
if (!options?.withInternalKyselyTables &&
|
|
45
|
+
if (!options?.withInternalKyselyTables &&
|
|
46
|
+
(row.table_name.includes('kysely_') ||
|
|
47
|
+
row.table_name.includes('noorm_'))) {
|
|
46
48
|
continue;
|
|
47
49
|
}
|
|
48
50
|
tables.push({
|
|
@@ -114,7 +114,9 @@ class PostgresConnection {
|
|
|
114
114
|
if (result.command === 'INSERT' && result.rows.length > 0) {
|
|
115
115
|
const firstRow = result.rows[0];
|
|
116
116
|
const idValue = firstRow.id ?? firstRow.ID ?? Object.values(firstRow)[0];
|
|
117
|
-
if (typeof idValue === 'number' ||
|
|
117
|
+
if (typeof idValue === 'number' ||
|
|
118
|
+
typeof idValue === 'bigint' ||
|
|
119
|
+
typeof idValue === 'string') {
|
|
118
120
|
try {
|
|
119
121
|
insertId = BigInt(idValue);
|
|
120
122
|
}
|
|
@@ -25,7 +25,9 @@ exports.PostgresArrayHelpers = {
|
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
27
|
array(values) {
|
|
28
|
-
const literalValues = values
|
|
28
|
+
const literalValues = values
|
|
29
|
+
.map((v) => typeof v === 'string' ? `'${v.replace(/'/g, "''")}'` : String(v))
|
|
30
|
+
.join(', ');
|
|
29
31
|
return (0, sql_js_1.sql) `ARRAY[${sql_js_1.sql.raw(literalValues)}]`;
|
|
30
32
|
},
|
|
31
33
|
/**
|
|
@@ -86,7 +88,9 @@ exports.PostgresArrayHelpers = {
|
|
|
86
88
|
* ```
|
|
87
89
|
*/
|
|
88
90
|
append(column, value) {
|
|
89
|
-
const literal = typeof value === 'string'
|
|
91
|
+
const literal = typeof value === 'string'
|
|
92
|
+
? `'${value.replace(/'/g, "''")}'`
|
|
93
|
+
: String(value);
|
|
90
94
|
return (0, sql_js_1.sql) `array_append(${sql_js_1.sql.ref(column)}, ${sql_js_1.sql.raw(literal)})`;
|
|
91
95
|
},
|
|
92
96
|
/**
|
|
@@ -99,7 +103,9 @@ exports.PostgresArrayHelpers = {
|
|
|
99
103
|
* ```
|
|
100
104
|
*/
|
|
101
105
|
remove(column, value) {
|
|
102
|
-
const literal = typeof value === 'string'
|
|
106
|
+
const literal = typeof value === 'string'
|
|
107
|
+
? `'${value.replace(/'/g, "''")}'`
|
|
108
|
+
: String(value);
|
|
103
109
|
return (0, sql_js_1.sql) `array_remove(${sql_js_1.sql.ref(column)}, ${sql_js_1.sql.raw(literal)})`;
|
|
104
110
|
},
|
|
105
111
|
/**
|
|
@@ -178,7 +184,7 @@ exports.PostgresJSONHelpers = {
|
|
|
178
184
|
* ```
|
|
179
185
|
*/
|
|
180
186
|
hasAnyKey(column, keys) {
|
|
181
|
-
return (0, sql_js_1.sql) `${sql_js_1.sql.ref(column)} ?| ARRAY[${keys.map(k => `'${k}'`).join(', ')}]`;
|
|
187
|
+
return (0, sql_js_1.sql) `${sql_js_1.sql.ref(column)} ?| ARRAY[${keys.map((k) => `'${k}'`).join(', ')}]`;
|
|
182
188
|
},
|
|
183
189
|
/**
|
|
184
190
|
* Check if JSON contains all keys
|
|
@@ -190,7 +196,7 @@ exports.PostgresJSONHelpers = {
|
|
|
190
196
|
* ```
|
|
191
197
|
*/
|
|
192
198
|
hasAllKeys(column, keys) {
|
|
193
|
-
return (0, sql_js_1.sql) `${sql_js_1.sql.ref(column)} ?& ARRAY[${keys.map(k => `'${k}'`).join(', ')}]`;
|
|
199
|
+
return (0, sql_js_1.sql) `${sql_js_1.sql.ref(column)} ?& ARRAY[${keys.map((k) => `'${k}'`).join(', ')}]`;
|
|
194
200
|
},
|
|
195
201
|
/**
|
|
196
202
|
* Check if JSONB contains value
|
|
@@ -347,7 +353,9 @@ exports.PostgresFullTextHelpers = {
|
|
|
347
353
|
* ```
|
|
348
354
|
*/
|
|
349
355
|
async addGeneratedTSVectorColumn(db, table, columnName, sourceColumns, config = 'english') {
|
|
350
|
-
const concatenated = sourceColumns
|
|
356
|
+
const concatenated = sourceColumns
|
|
357
|
+
.map((col) => `coalesce(${col}, '')`)
|
|
358
|
+
.join(` || ' ' || `);
|
|
351
359
|
await (0, sql_js_1.sql) `
|
|
352
360
|
ALTER TABLE ${sql_js_1.sql.table(table)}
|
|
353
361
|
ADD COLUMN IF NOT EXISTS ${sql_js_1.sql.ref(columnName)} tsvector
|
|
@@ -373,7 +381,9 @@ exports.PostgresMaterializedViewHelpers = {
|
|
|
373
381
|
*/
|
|
374
382
|
async create(db, viewName, query, options) {
|
|
375
383
|
const withData = options?.withData !== false ? 'WITH DATA' : 'WITH NO DATA';
|
|
376
|
-
const tablespace = options?.tablespace
|
|
384
|
+
const tablespace = options?.tablespace
|
|
385
|
+
? `TABLESPACE ${options.tablespace}`
|
|
386
|
+
: '';
|
|
377
387
|
await (0, sql_js_1.sql) `
|
|
378
388
|
CREATE MATERIALIZED VIEW IF NOT EXISTS ${sql_js_1.sql.ref(viewName)}
|
|
379
389
|
${sql_js_1.sql.raw(tablespace)}
|
|
@@ -426,7 +436,7 @@ exports.PostgresMaterializedViewHelpers = {
|
|
|
426
436
|
*/
|
|
427
437
|
async createUniqueIndex(db, viewName, columns, indexName) {
|
|
428
438
|
const name = indexName || `${viewName}_${columns.join('_')}_idx`;
|
|
429
|
-
const columnList = columns.map(c => sql_js_1.sql.ref(c)).join(', ');
|
|
439
|
+
const columnList = columns.map((c) => sql_js_1.sql.ref(c)).join(', ');
|
|
430
440
|
await (0, sql_js_1.sql) `
|
|
431
441
|
CREATE UNIQUE INDEX IF NOT EXISTS ${sql_js_1.sql.ref(name)}
|
|
432
442
|
ON ${sql_js_1.sql.ref(viewName)} (${sql_js_1.sql.raw(columnList)})
|
|
@@ -235,7 +235,7 @@ class PostgresIntrospector extends database_introspector_js_1.DatabaseIntrospect
|
|
|
235
235
|
// Map PostgreSQL element types to standard types
|
|
236
236
|
const elementTypeMap = {
|
|
237
237
|
'character varying': 'varchar',
|
|
238
|
-
|
|
238
|
+
character: 'char',
|
|
239
239
|
'timestamp without time zone': 'timestamp',
|
|
240
240
|
'timestamp with time zone': 'timestamptz',
|
|
241
241
|
'time without time zone': 'time',
|
|
@@ -253,7 +253,7 @@ class PostgresIntrospector extends database_introspector_js_1.DatabaseIntrospect
|
|
|
253
253
|
// Map common PostgreSQL types to standard names
|
|
254
254
|
const typeMap = {
|
|
255
255
|
'character varying': 'varchar',
|
|
256
|
-
|
|
256
|
+
character: 'char',
|
|
257
257
|
'timestamp without time zone': 'timestamp',
|
|
258
258
|
'timestamp with time zone': 'timestamptz',
|
|
259
259
|
'time without time zone': 'time',
|
|
@@ -32,7 +32,9 @@ class SQLiteAutoIndexer {
|
|
|
32
32
|
pattern.frequency++;
|
|
33
33
|
pattern.lastExecuted = new Date();
|
|
34
34
|
pattern.averageExecutionTime =
|
|
35
|
-
(pattern.averageExecutionTime * (pattern.frequency - 1) +
|
|
35
|
+
(pattern.averageExecutionTime * (pattern.frequency - 1) +
|
|
36
|
+
executionTime) /
|
|
37
|
+
pattern.frequency;
|
|
36
38
|
}
|
|
37
39
|
else {
|
|
38
40
|
// Create new pattern
|
|
@@ -44,7 +46,7 @@ class SQLiteAutoIndexer {
|
|
|
44
46
|
orderByColumns: this.extractOrderByColumns(query),
|
|
45
47
|
joinColumns: this.extractJoinColumns(query),
|
|
46
48
|
lastExecuted: new Date(),
|
|
47
|
-
averageExecutionTime: executionTime
|
|
49
|
+
averageExecutionTime: executionTime,
|
|
48
50
|
};
|
|
49
51
|
this.queryPatterns.set(normalizedQuery, newPattern);
|
|
50
52
|
}
|
|
@@ -53,13 +55,13 @@ class SQLiteAutoIndexer {
|
|
|
53
55
|
* Analyze query patterns and generate index recommendations
|
|
54
56
|
*/
|
|
55
57
|
async analyzeAndRecommend(db, options = {}) {
|
|
56
|
-
const { minFrequency = 3, slowQueryThreshold = 1000, includePartialIndexes = true, maxRecommendations = 20 } = options;
|
|
58
|
+
const { minFrequency = 3, slowQueryThreshold = 1000, includePartialIndexes = true, maxRecommendations = 20, } = options;
|
|
57
59
|
try {
|
|
58
60
|
// Get existing indexes
|
|
59
61
|
await this.loadExistingIndexes(db);
|
|
60
62
|
// Filter relevant patterns
|
|
61
63
|
const relevantPatterns = Array.from(this.queryPatterns.values())
|
|
62
|
-
.filter(pattern => pattern.frequency >= minFrequency ||
|
|
64
|
+
.filter((pattern) => pattern.frequency >= minFrequency ||
|
|
63
65
|
pattern.averageExecutionTime > slowQueryThreshold)
|
|
64
66
|
.sort((a, b) => b.frequency - a.frequency);
|
|
65
67
|
// Generate recommendations
|
|
@@ -78,7 +80,7 @@ class SQLiteAutoIndexer {
|
|
|
78
80
|
redundantIndexes,
|
|
79
81
|
missingIndexes,
|
|
80
82
|
performanceImpact: this.calculatePerformanceImpact(limitedRecommendations),
|
|
81
|
-
summary: this.generateSummary(limitedRecommendations, redundantIndexes)
|
|
83
|
+
summary: this.generateSummary(limitedRecommendations, redundantIndexes),
|
|
82
84
|
};
|
|
83
85
|
// Store analysis history
|
|
84
86
|
const dbId = await this.getDatabaseId(db);
|
|
@@ -126,7 +128,9 @@ class SQLiteAutoIndexer {
|
|
|
126
128
|
const recommendations = [];
|
|
127
129
|
for (const column of pattern.whereColumns) {
|
|
128
130
|
// Check if index already exists
|
|
129
|
-
const existingIndex = await this.findExistingIndex(db, pattern.table, [
|
|
131
|
+
const existingIndex = await this.findExistingIndex(db, pattern.table, [
|
|
132
|
+
column,
|
|
133
|
+
]);
|
|
130
134
|
if (existingIndex)
|
|
131
135
|
continue;
|
|
132
136
|
const priority = this.calculateWherePriority(pattern, column);
|
|
@@ -138,7 +142,7 @@ class SQLiteAutoIndexer {
|
|
|
138
142
|
priority,
|
|
139
143
|
reason: `Frequently queried column (${pattern.frequency} times, avg ${Math.round(pattern.averageExecutionTime)}ms)`,
|
|
140
144
|
estimatedImpact: this.estimateImpact(pattern),
|
|
141
|
-
sql: this.generateIndexSQL(pattern.table, [column], type, includePartialIndexes)
|
|
145
|
+
sql: this.generateIndexSQL(pattern.table, [column], type, includePartialIndexes),
|
|
142
146
|
});
|
|
143
147
|
}
|
|
144
148
|
// Composite indexes for multiple WHERE columns
|
|
@@ -156,7 +160,9 @@ class SQLiteAutoIndexer {
|
|
|
156
160
|
async generateOrderByIndexes(db, pattern, includePartialIndexes) {
|
|
157
161
|
const recommendations = [];
|
|
158
162
|
for (const column of pattern.orderByColumns) {
|
|
159
|
-
const existingIndex = await this.findExistingIndex(db, pattern.table, [
|
|
163
|
+
const existingIndex = await this.findExistingIndex(db, pattern.table, [
|
|
164
|
+
column,
|
|
165
|
+
]);
|
|
160
166
|
if (existingIndex)
|
|
161
167
|
continue;
|
|
162
168
|
recommendations.push({
|
|
@@ -166,7 +172,7 @@ class SQLiteAutoIndexer {
|
|
|
166
172
|
priority: 'medium',
|
|
167
173
|
reason: `Frequently ordered by column (${pattern.frequency} times)`,
|
|
168
174
|
estimatedImpact: 'medium',
|
|
169
|
-
sql: this.generateIndexSQL(pattern.table, [column], 'single', includePartialIndexes)
|
|
175
|
+
sql: this.generateIndexSQL(pattern.table, [column], 'single', includePartialIndexes),
|
|
170
176
|
});
|
|
171
177
|
}
|
|
172
178
|
return recommendations;
|
|
@@ -177,7 +183,9 @@ class SQLiteAutoIndexer {
|
|
|
177
183
|
async generateJoinIndexes(db, pattern, includePartialIndexes) {
|
|
178
184
|
const recommendations = [];
|
|
179
185
|
for (const column of pattern.joinColumns) {
|
|
180
|
-
const existingIndex = await this.findExistingIndex(db, pattern.table, [
|
|
186
|
+
const existingIndex = await this.findExistingIndex(db, pattern.table, [
|
|
187
|
+
column,
|
|
188
|
+
]);
|
|
181
189
|
if (existingIndex)
|
|
182
190
|
continue;
|
|
183
191
|
recommendations.push({
|
|
@@ -187,7 +195,7 @@ class SQLiteAutoIndexer {
|
|
|
187
195
|
priority: 'high',
|
|
188
196
|
reason: `Foreign key column used in joins (${pattern.frequency} times)`,
|
|
189
197
|
estimatedImpact: 'high',
|
|
190
|
-
sql: this.generateIndexSQL(pattern.table, [column], 'single', includePartialIndexes)
|
|
198
|
+
sql: this.generateIndexSQL(pattern.table, [column], 'single', includePartialIndexes),
|
|
191
199
|
});
|
|
192
200
|
}
|
|
193
201
|
return recommendations;
|
|
@@ -207,7 +215,7 @@ class SQLiteAutoIndexer {
|
|
|
207
215
|
priority: 'high',
|
|
208
216
|
reason: `Composite index for multiple WHERE columns (${pattern.frequency} times)`,
|
|
209
217
|
estimatedImpact: 'high',
|
|
210
|
-
sql: this.generateIndexSQL(pattern.table, columns, 'composite', includePartialIndexes)
|
|
218
|
+
sql: this.generateIndexSQL(pattern.table, columns, 'composite', includePartialIndexes),
|
|
211
219
|
};
|
|
212
220
|
}
|
|
213
221
|
/**
|
|
@@ -271,12 +279,14 @@ class SQLiteAutoIndexer {
|
|
|
271
279
|
this.existingIndexes.clear();
|
|
272
280
|
for (const row of result) {
|
|
273
281
|
const columns = this.extractColumnsFromSQL(row.sql || '');
|
|
274
|
-
this.existingIndexes.set(row.name, [
|
|
282
|
+
this.existingIndexes.set(row.name, [
|
|
283
|
+
{
|
|
275
284
|
name: row.name,
|
|
276
285
|
table: row.tbl_name,
|
|
277
286
|
columns,
|
|
278
|
-
sql: row.sql
|
|
279
|
-
}
|
|
287
|
+
sql: row.sql,
|
|
288
|
+
},
|
|
289
|
+
]);
|
|
280
290
|
}
|
|
281
291
|
}
|
|
282
292
|
catch (error) {
|
|
@@ -301,8 +311,7 @@ class SQLiteAutoIndexer {
|
|
|
301
311
|
async findExistingIndex(db, table, columns) {
|
|
302
312
|
for (const [indexName, indexes] of this.existingIndexes.entries()) {
|
|
303
313
|
for (const index of indexes) {
|
|
304
|
-
if (index.table === table &&
|
|
305
|
-
this.arraysEqual(index.columns, columns)) {
|
|
314
|
+
if (index.table === table && this.arraysEqual(index.columns, columns)) {
|
|
306
315
|
return indexName;
|
|
307
316
|
}
|
|
308
317
|
}
|
|
@@ -345,7 +354,7 @@ class SQLiteAutoIndexer {
|
|
|
345
354
|
*/
|
|
346
355
|
generateIndexSQL(table, columns, type, includePartialIndexes) {
|
|
347
356
|
const indexName = this.generateIndexName(table, columns);
|
|
348
|
-
const columnList = columns.map(col => `"${col}"`).join(', ');
|
|
357
|
+
const columnList = columns.map((col) => `"${col}"`).join(', ');
|
|
349
358
|
let sql = `CREATE INDEX "${indexName}" ON "${table}" (${columnList})`;
|
|
350
359
|
if (type === 'unique') {
|
|
351
360
|
sql = sql.replace('CREATE INDEX', 'CREATE UNIQUE INDEX');
|
|
@@ -365,14 +374,15 @@ class SQLiteAutoIndexer {
|
|
|
365
374
|
getPriorityScore(recommendation) {
|
|
366
375
|
const priorityScores = { critical: 4, high: 3, medium: 2, low: 1 };
|
|
367
376
|
const impactScores = { high: 3, medium: 2, low: 1 };
|
|
368
|
-
return priorityScores[recommendation.priority] *
|
|
377
|
+
return (priorityScores[recommendation.priority] *
|
|
378
|
+
impactScores[recommendation.estimatedImpact]);
|
|
369
379
|
}
|
|
370
380
|
/**
|
|
371
381
|
* Calculate overall performance impact
|
|
372
382
|
*/
|
|
373
383
|
calculatePerformanceImpact(recommendations) {
|
|
374
|
-
const highImpactCount = recommendations.filter(r => r.estimatedImpact === 'high').length;
|
|
375
|
-
const mediumImpactCount = recommendations.filter(r => r.estimatedImpact === 'medium').length;
|
|
384
|
+
const highImpactCount = recommendations.filter((r) => r.estimatedImpact === 'high').length;
|
|
385
|
+
const mediumImpactCount = recommendations.filter((r) => r.estimatedImpact === 'medium').length;
|
|
376
386
|
if (highImpactCount > 3)
|
|
377
387
|
return 'high';
|
|
378
388
|
if (highImpactCount > 0 || mediumImpactCount > 5)
|
|
@@ -383,8 +393,8 @@ class SQLiteAutoIndexer {
|
|
|
383
393
|
* Generate analysis summary
|
|
384
394
|
*/
|
|
385
395
|
generateSummary(recommendations, redundantIndexes) {
|
|
386
|
-
const criticalCount = recommendations.filter(r => r.priority === 'critical').length;
|
|
387
|
-
const highCount = recommendations.filter(r => r.priority === 'high').length;
|
|
396
|
+
const criticalCount = recommendations.filter((r) => r.priority === 'critical').length;
|
|
397
|
+
const highCount = recommendations.filter((r) => r.priority === 'high').length;
|
|
388
398
|
const redundantCount = redundantIndexes.length;
|
|
389
399
|
let summary = `Found ${recommendations.length} index recommendations`;
|
|
390
400
|
if (criticalCount > 0) {
|
|
@@ -403,7 +413,7 @@ class SQLiteAutoIndexer {
|
|
|
403
413
|
*/
|
|
404
414
|
deduplicateRecommendations(recommendations) {
|
|
405
415
|
const seen = new Set();
|
|
406
|
-
return recommendations.filter(rec => {
|
|
416
|
+
return recommendations.filter((rec) => {
|
|
407
417
|
const key = `${rec.table}:${rec.columns.join(',')}`;
|
|
408
418
|
if (seen.has(key))
|
|
409
419
|
return false;
|
|
@@ -427,8 +437,9 @@ class SQLiteAutoIndexer {
|
|
|
427
437
|
return [];
|
|
428
438
|
const whereClause = whereMatch[1];
|
|
429
439
|
const columnMatches = whereClause.match(/(\w+)\s*[=<>]/g);
|
|
430
|
-
return columnMatches
|
|
431
|
-
columnMatches.map(match => match.replace(/\s*[=<>].*/, '').trim())
|
|
440
|
+
return columnMatches
|
|
441
|
+
? columnMatches.map((match) => match.replace(/\s*[=<>].*/, '').trim())
|
|
442
|
+
: [];
|
|
432
443
|
}
|
|
433
444
|
/**
|
|
434
445
|
* Extract ORDER BY columns from query
|
|
@@ -440,8 +451,11 @@ class SQLiteAutoIndexer {
|
|
|
440
451
|
const orderClause = orderMatch[1];
|
|
441
452
|
return orderClause
|
|
442
453
|
.split(',')
|
|
443
|
-
.map(col => col
|
|
444
|
-
.
|
|
454
|
+
.map((col) => col
|
|
455
|
+
.trim()
|
|
456
|
+
.replace(/\s+(ASC|DESC).*$/i, '')
|
|
457
|
+
.replace(/["`]/g, ''))
|
|
458
|
+
.filter((col) => col.length > 0);
|
|
445
459
|
}
|
|
446
460
|
/**
|
|
447
461
|
* Extract JOIN columns from query
|
|
@@ -455,7 +469,7 @@ class SQLiteAutoIndexer {
|
|
|
455
469
|
const onClause = match.replace(/JOIN\s+\w+\s+ON\s+/i, '');
|
|
456
470
|
const columnMatches = onClause.match(/(\w+)\s*=/g);
|
|
457
471
|
if (columnMatches) {
|
|
458
|
-
columns.push(...columnMatches.map(m => m.replace(/\s*=.*/, '').trim()));
|
|
472
|
+
columns.push(...columnMatches.map((m) => m.replace(/\s*=.*/, '').trim()));
|
|
459
473
|
}
|
|
460
474
|
}
|
|
461
475
|
return columns;
|
|
@@ -470,8 +484,8 @@ class SQLiteAutoIndexer {
|
|
|
470
484
|
if (match) {
|
|
471
485
|
return match[1]
|
|
472
486
|
.split(',')
|
|
473
|
-
.map(col => col.trim().replace(/^\s*["']?|["']?\s*$/g, ''))
|
|
474
|
-
.filter(col => col.length > 0);
|
|
487
|
+
.map((col) => col.trim().replace(/^\s*["']?|["']?\s*$/g, ''))
|
|
488
|
+
.filter((col) => col.length > 0);
|
|
475
489
|
}
|
|
476
490
|
return [];
|
|
477
491
|
}
|
|
@@ -529,12 +543,12 @@ class SQLiteAutoIndexer {
|
|
|
529
543
|
const patterns = Array.from(this.queryPatterns.values());
|
|
530
544
|
const totalQueries = patterns.reduce((sum, p) => sum + p.frequency, 0);
|
|
531
545
|
const averageFrequency = patterns.length > 0 ? totalQueries / patterns.length : 0;
|
|
532
|
-
const slowQueries = patterns.filter(p => p.averageExecutionTime > 1000).length;
|
|
546
|
+
const slowQueries = patterns.filter((p) => p.averageExecutionTime > 1000).length;
|
|
533
547
|
return {
|
|
534
548
|
totalPatterns: patterns.length,
|
|
535
549
|
totalQueries,
|
|
536
550
|
averageFrequency,
|
|
537
|
-
slowQueries
|
|
551
|
+
slowQueries,
|
|
538
552
|
};
|
|
539
553
|
}
|
|
540
554
|
}
|
|
@@ -33,7 +33,7 @@ class SQLiteAutoOptimizer {
|
|
|
33
33
|
journalMode: 'WAL',
|
|
34
34
|
synchronous: 'NORMAL',
|
|
35
35
|
cacheSize: -64000, // 64MB cache
|
|
36
|
-
tempStore: 'MEMORY'
|
|
36
|
+
tempStore: 'MEMORY',
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
@@ -41,7 +41,7 @@ class SQLiteAutoOptimizer {
|
|
|
41
41
|
*/
|
|
42
42
|
async analyzeDatabase(db) {
|
|
43
43
|
try {
|
|
44
|
-
const [pageCount, pageSize, freelistCount, schemaVersion, userVersion, applicationId, cacheSize, synchronous, journalMode, autoVacuum, tempStore, foreignKeys] = await Promise.all([
|
|
44
|
+
const [pageCount, pageSize, freelistCount, schemaVersion, userVersion, applicationId, cacheSize, synchronous, journalMode, autoVacuum, tempStore, foreignKeys,] = await Promise.all([
|
|
45
45
|
this.getPragmaValue(db, 'page_count'),
|
|
46
46
|
this.getPragmaValue(db, 'page_size'),
|
|
47
47
|
this.getPragmaValue(db, 'freelist_count'),
|
|
@@ -53,7 +53,7 @@ class SQLiteAutoOptimizer {
|
|
|
53
53
|
this.getPragmaValue(db, 'journal_mode'),
|
|
54
54
|
this.getPragmaValue(db, 'auto_vacuum'),
|
|
55
55
|
this.getPragmaValue(db, 'temp_store'),
|
|
56
|
-
this.getPragmaValue(db, 'foreign_keys')
|
|
56
|
+
this.getPragmaValue(db, 'foreign_keys'),
|
|
57
57
|
]);
|
|
58
58
|
// Run integrity check
|
|
59
59
|
const integrityResult = await (0, sql_js_1.sql) `PRAGMA integrity_check`.execute(db);
|
|
@@ -72,7 +72,7 @@ class SQLiteAutoOptimizer {
|
|
|
72
72
|
autoVacuum: Number(autoVacuum),
|
|
73
73
|
tempStore: Number(tempStore),
|
|
74
74
|
foreignKeys: Number(foreignKeys),
|
|
75
|
-
integrityCheck
|
|
75
|
+
integrityCheck,
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
78
|
catch (error) {
|
|
@@ -88,7 +88,7 @@ class SQLiteAutoOptimizer {
|
|
|
88
88
|
appliedOptimizations: [],
|
|
89
89
|
recommendations: [],
|
|
90
90
|
performanceImpact: 'low',
|
|
91
|
-
warnings: []
|
|
91
|
+
warnings: [],
|
|
92
92
|
};
|
|
93
93
|
try {
|
|
94
94
|
// Analyze current state
|
|
@@ -288,7 +288,7 @@ class SQLiteAutoOptimizer {
|
|
|
288
288
|
.where('type', '=', 'table')
|
|
289
289
|
.where('name', 'not like', 'sqlite_%')
|
|
290
290
|
.execute();
|
|
291
|
-
return result.map(row => row.name);
|
|
291
|
+
return result.map((row) => row.name);
|
|
292
292
|
}
|
|
293
293
|
catch (error) {
|
|
294
294
|
this.logger.debug('Failed to get table list:', error);
|
|
@@ -334,7 +334,8 @@ class SQLiteAutoOptimizer {
|
|
|
334
334
|
}
|
|
335
335
|
// Check database size
|
|
336
336
|
const dbSize = metrics.pageCount * metrics.pageSize;
|
|
337
|
-
if (dbSize > 100 * 1024 * 1024) {
|
|
337
|
+
if (dbSize > 100 * 1024 * 1024) {
|
|
338
|
+
// 100MB
|
|
338
339
|
recommendations.push('For large databases, consider using SQLite backup API or .backup command for efficient backups.');
|
|
339
340
|
}
|
|
340
341
|
// Check for active transactions
|