noormme 1.0.6 → 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 +92 -63
- package/dist/cjs/agentic/ActionJournal.js +13 -9
- package/dist/cjs/agentic/CapabilityManager.d.ts +9 -4
- package/dist/cjs/agentic/CapabilityManager.js +113 -17
- package/dist/cjs/agentic/CognitiveRepository.js +19 -9
- package/dist/cjs/agentic/ContextBuffer.js +24 -12
- package/dist/cjs/agentic/Cortex.d.ts +8 -1
- package/dist/cjs/agentic/Cortex.js +30 -7
- 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.d.ts +1 -1
- package/dist/cjs/agentic/improvement/CortexJanitor.js +64 -27
- package/dist/cjs/agentic/improvement/CuriosityEngine.d.ts +2 -2
- package/dist/cjs/agentic/improvement/CuriosityEngine.js +68 -59
- package/dist/cjs/agentic/improvement/EvolutionRitual.d.ts +24 -0
- package/dist/cjs/agentic/improvement/EvolutionRitual.js +91 -0
- package/dist/cjs/agentic/improvement/EvolutionaryPilot.d.ts +5 -0
- package/dist/cjs/agentic/improvement/EvolutionaryPilot.js +80 -7
- 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.d.ts +1 -1
- package/dist/cjs/agentic/improvement/GovernanceManager.js +85 -49
- package/dist/cjs/agentic/improvement/HiveLink.d.ts +9 -0
- package/dist/cjs/agentic/improvement/HiveLink.js +120 -26
- package/dist/cjs/agentic/improvement/KnowledgeDistiller.d.ts +2 -0
- package/dist/cjs/agentic/improvement/KnowledgeDistiller.js +101 -47
- package/dist/cjs/agentic/improvement/RecursiveReasoner.d.ts +7 -1
- package/dist/cjs/agentic/improvement/RecursiveReasoner.js +106 -22
- package/dist/cjs/agentic/improvement/ReflectionEngine.js +10 -8
- package/dist/cjs/agentic/improvement/RitualOrchestrator.js +34 -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.d.ts +48 -0
- package/dist/cjs/agentic/improvement/SkillSynthesizer.js +288 -0
- package/dist/cjs/agentic/improvement/SovereignMetrics.js +19 -17
- package/dist/cjs/agentic/improvement/StrategicPlanner.d.ts +1 -1
- package/dist/cjs/agentic/improvement/StrategicPlanner.js +129 -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 +13 -4
- 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 +3 -0
- package/dist/cjs/helpers/postgresql.js +7 -4
- package/dist/cjs/helpers/schema-evolution.js +31 -6
- package/dist/cjs/index.d.ts +18 -16
- 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 +54 -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 +61 -4
- 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.d.ts +9 -4
- package/dist/esm/agentic/CapabilityManager.js +113 -17
- package/dist/esm/agentic/CognitiveRepository.js +19 -9
- package/dist/esm/agentic/ContextBuffer.js +24 -12
- package/dist/esm/agentic/Cortex.d.ts +8 -1
- package/dist/esm/agentic/Cortex.js +30 -7
- 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.d.ts +1 -1
- package/dist/esm/agentic/improvement/CortexJanitor.js +64 -27
- package/dist/esm/agentic/improvement/CuriosityEngine.d.ts +2 -2
- package/dist/esm/agentic/improvement/CuriosityEngine.js +68 -59
- package/dist/esm/agentic/improvement/EvolutionRitual.d.ts +24 -0
- package/dist/esm/agentic/improvement/EvolutionRitual.js +88 -0
- package/dist/esm/agentic/improvement/EvolutionaryPilot.d.ts +5 -0
- package/dist/esm/agentic/improvement/EvolutionaryPilot.js +80 -7
- 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.d.ts +1 -1
- package/dist/esm/agentic/improvement/GovernanceManager.js +85 -49
- package/dist/esm/agentic/improvement/HiveLink.d.ts +9 -0
- package/dist/esm/agentic/improvement/HiveLink.js +120 -26
- package/dist/esm/agentic/improvement/KnowledgeDistiller.d.ts +2 -0
- package/dist/esm/agentic/improvement/KnowledgeDistiller.js +101 -47
- package/dist/esm/agentic/improvement/RecursiveReasoner.d.ts +7 -1
- package/dist/esm/agentic/improvement/RecursiveReasoner.js +106 -22
- package/dist/esm/agentic/improvement/ReflectionEngine.js +10 -8
- package/dist/esm/agentic/improvement/RitualOrchestrator.js +34 -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.d.ts +48 -0
- package/dist/esm/agentic/improvement/SkillSynthesizer.js +285 -0
- package/dist/esm/agentic/improvement/SovereignMetrics.js +19 -17
- package/dist/esm/agentic/improvement/StrategicPlanner.d.ts +1 -1
- package/dist/esm/agentic/improvement/StrategicPlanner.js +129 -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 +13 -4
- 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 +3 -0
- package/dist/esm/helpers/postgresql.js +7 -4
- package/dist/esm/helpers/schema-evolution.js +31 -6
- package/dist/esm/index.d.ts +18 -16
- 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 +54 -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 +61 -4
- 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
package/dist/esm/noormme.js
CHANGED
|
@@ -81,7 +81,9 @@ export class NOORMME {
|
|
|
81
81
|
this.dialect = this.createDialect();
|
|
82
82
|
this.db = new Kysely({
|
|
83
83
|
dialect: this.dialect,
|
|
84
|
-
log: this.config.logging?.enabled
|
|
84
|
+
log: this.config.logging?.enabled
|
|
85
|
+
? this.logger.createKyselyLogger()
|
|
86
|
+
: undefined,
|
|
85
87
|
});
|
|
86
88
|
// Initialize core components
|
|
87
89
|
this.schemaDiscovery = new SchemaDiscovery(this.db, this.config.introspection, this.dialect);
|
|
@@ -95,7 +97,7 @@ export class NOORMME {
|
|
|
95
97
|
: null,
|
|
96
98
|
schema: new AgentSchemaHelper(this.db, agenticConfig),
|
|
97
99
|
cortex: new Cortex(this.db, this.config),
|
|
98
|
-
evolution: new SchemaEvolutionHelper(this.db)
|
|
100
|
+
evolution: new SchemaEvolutionHelper(this.db),
|
|
99
101
|
};
|
|
100
102
|
this.repositoryFactory = new RepositoryFactory(this.db, this.config.performance, this.agent.cortex);
|
|
101
103
|
this.relationshipEngine = new RelationshipEngine(this.db, this.config.performance);
|
|
@@ -162,7 +164,7 @@ export class NOORMME {
|
|
|
162
164
|
schemaInfo = {
|
|
163
165
|
tables: [],
|
|
164
166
|
relationships: [],
|
|
165
|
-
views: []
|
|
167
|
+
views: [],
|
|
166
168
|
};
|
|
167
169
|
}
|
|
168
170
|
// Generate types - handle empty schema gracefully
|
|
@@ -178,7 +180,7 @@ export class NOORMME {
|
|
|
178
180
|
generatedTypes = {
|
|
179
181
|
entities: [],
|
|
180
182
|
relationships: [],
|
|
181
|
-
types: {}
|
|
183
|
+
types: {},
|
|
182
184
|
};
|
|
183
185
|
}
|
|
184
186
|
// Cache schema and types - handle caching errors gracefully
|
|
@@ -202,7 +204,7 @@ export class NOORMME {
|
|
|
202
204
|
slowQueryThreshold: 1000,
|
|
203
205
|
nPlusOneDetection: true,
|
|
204
206
|
missingIndexDetection: true,
|
|
205
|
-
persistPath: process.env.NOORMME_METRICS_PATH || '.noormme/metrics.json'
|
|
207
|
+
persistPath: process.env.NOORMME_METRICS_PATH || '.noormme/metrics.json',
|
|
206
208
|
}, this.logger);
|
|
207
209
|
// Initialize SQLite-specific auto-optimization features
|
|
208
210
|
if (this.config.dialect === 'sqlite') {
|
|
@@ -240,15 +242,15 @@ export class NOORMME {
|
|
|
240
242
|
const result = await this.sqliteAutoOptimizer.optimizeDatabase(this.db, config);
|
|
241
243
|
if (result.appliedOptimizations.length > 0) {
|
|
242
244
|
this.logger.info(`Applied ${result.appliedOptimizations.length} SQLite optimizations`);
|
|
243
|
-
result.appliedOptimizations.forEach(opt => this.logger.debug(` ✓ ${opt}`));
|
|
245
|
+
result.appliedOptimizations.forEach((opt) => this.logger.debug(` ✓ ${opt}`));
|
|
244
246
|
}
|
|
245
247
|
if (result.recommendations.length > 0) {
|
|
246
248
|
this.logger.info(`Generated ${result.recommendations.length} recommendations`);
|
|
247
|
-
result.recommendations.forEach(rec => this.logger.debug(` 💡 ${rec}`));
|
|
249
|
+
result.recommendations.forEach((rec) => this.logger.debug(` 💡 ${rec}`));
|
|
248
250
|
}
|
|
249
251
|
if (result.warnings.length > 0) {
|
|
250
252
|
this.logger.warn(`Found ${result.warnings.length} warnings`);
|
|
251
|
-
result.warnings.forEach(warning => this.logger.warn(` ⚠️ ${warning}`));
|
|
253
|
+
result.warnings.forEach((warning) => this.logger.warn(` ⚠️ ${warning}`));
|
|
252
254
|
}
|
|
253
255
|
}
|
|
254
256
|
catch (error) {
|
|
@@ -333,9 +335,9 @@ export class NOORMME {
|
|
|
333
335
|
if (!schemaInfo) {
|
|
334
336
|
throw new Error('Schema not found. Please reinitialize NOORMME.');
|
|
335
337
|
}
|
|
336
|
-
const table = schemaInfo.tables.find(t => t.name === tableName);
|
|
338
|
+
const table = schemaInfo.tables.find((t) => t.name === tableName);
|
|
337
339
|
if (!table) {
|
|
338
|
-
const availableTables = schemaInfo.tables.map(t => t.name);
|
|
340
|
+
const availableTables = schemaInfo.tables.map((t) => t.name);
|
|
339
341
|
throw new TableNotFoundError(tableName, availableTables);
|
|
340
342
|
}
|
|
341
343
|
const repository = this.repositoryFactory.createRepository(table, schemaInfo.relationships);
|
|
@@ -406,7 +408,7 @@ export class NOORMME {
|
|
|
406
408
|
// Auto-refresh schema when changes detected
|
|
407
409
|
this.schemaWatcher.onSchemaChange(async (changes) => {
|
|
408
410
|
this.logger.info(`Schema changes detected: ${changes.length} changes`);
|
|
409
|
-
changes.forEach(change => {
|
|
411
|
+
changes.forEach((change) => {
|
|
410
412
|
this.logger.info(` - ${change.type}: ${change.table}`);
|
|
411
413
|
});
|
|
412
414
|
try {
|
|
@@ -447,12 +449,12 @@ export class NOORMME {
|
|
|
447
449
|
queryCount: this.logger.getQueryCount(),
|
|
448
450
|
averageQueryTime: this.logger.getAverageQueryTime(),
|
|
449
451
|
cacheHitRate: this.cacheManager.getHitRate(),
|
|
450
|
-
repositoryCount: this.repositories.size
|
|
452
|
+
repositoryCount: this.repositories.size,
|
|
451
453
|
};
|
|
452
454
|
if (this.metricsCollector) {
|
|
453
455
|
return {
|
|
454
456
|
...baseMetrics,
|
|
455
|
-
...this.metricsCollector.getPerformanceStats()
|
|
457
|
+
...this.metricsCollector.getPerformanceStats(),
|
|
456
458
|
};
|
|
457
459
|
}
|
|
458
460
|
return baseMetrics;
|
|
@@ -472,7 +474,7 @@ export class NOORMME {
|
|
|
472
474
|
enabled: true,
|
|
473
475
|
slowQueryThreshold: options?.slowQueryThreshold || 1000,
|
|
474
476
|
nPlusOneDetection: true,
|
|
475
|
-
missingIndexDetection: true
|
|
477
|
+
missingIndexDetection: true,
|
|
476
478
|
}, this.logger);
|
|
477
479
|
this.logger.info('Query performance monitoring enabled');
|
|
478
480
|
}
|
|
@@ -532,25 +534,27 @@ export class NOORMME {
|
|
|
532
534
|
includeViews: false,
|
|
533
535
|
excludeTables: [],
|
|
534
536
|
customTypeMappings: {},
|
|
535
|
-
...config.introspection
|
|
537
|
+
...config.introspection,
|
|
536
538
|
},
|
|
537
539
|
cache: {
|
|
538
540
|
ttl: 300000, // 5 minutes
|
|
539
541
|
maxSize: 1000,
|
|
540
542
|
strategy: 'lru',
|
|
541
|
-
...config.cache
|
|
543
|
+
...config.cache,
|
|
542
544
|
},
|
|
543
545
|
logging: {
|
|
544
546
|
level: 'info',
|
|
545
547
|
enabled: true,
|
|
546
|
-
...config.logging
|
|
548
|
+
...config.logging,
|
|
547
549
|
},
|
|
548
550
|
performance: {
|
|
549
551
|
enableQueryOptimization: true,
|
|
550
552
|
enableBatchLoading: true,
|
|
551
553
|
maxBatchSize: 100,
|
|
552
|
-
...config.performance
|
|
553
|
-
}
|
|
554
|
+
...config.performance,
|
|
555
|
+
},
|
|
556
|
+
agentic: config.agentic,
|
|
557
|
+
automation: config.automation,
|
|
554
558
|
};
|
|
555
559
|
}
|
|
556
560
|
/**
|
|
@@ -574,7 +578,7 @@ export class NOORMME {
|
|
|
574
578
|
default:
|
|
575
579
|
throw new NoormError(`Unsupported database protocol: ${url.protocol}`, {
|
|
576
580
|
operation: 'connection_string_parsing',
|
|
577
|
-
suggestion: 'Supported protocols: sqlite, postgresql, postgres, mysql'
|
|
581
|
+
suggestion: 'Supported protocols: sqlite, postgresql, postgres, mysql',
|
|
578
582
|
});
|
|
579
583
|
}
|
|
580
584
|
if (dialect === 'sqlite') {
|
|
@@ -585,8 +589,8 @@ export class NOORMME {
|
|
|
585
589
|
host: '',
|
|
586
590
|
port: 0,
|
|
587
591
|
username: '',
|
|
588
|
-
password: ''
|
|
589
|
-
}
|
|
592
|
+
password: '',
|
|
593
|
+
},
|
|
590
594
|
};
|
|
591
595
|
}
|
|
592
596
|
if (dialect === 'postgresql' || dialect === 'mysql') {
|
|
@@ -603,23 +607,31 @@ export class NOORMME {
|
|
|
603
607
|
}
|
|
604
608
|
else {
|
|
605
609
|
// For other SSL modes, we'll need more configuration
|
|
606
|
-
ssl = {
|
|
610
|
+
ssl = {
|
|
611
|
+
rejectUnauthorized: sslParam !== 'allow' && sslParam !== 'prefer',
|
|
612
|
+
};
|
|
607
613
|
}
|
|
608
614
|
}
|
|
609
615
|
return {
|
|
610
616
|
dialect,
|
|
611
617
|
connection: {
|
|
612
618
|
host: url.hostname || 'localhost',
|
|
613
|
-
port: url.port
|
|
619
|
+
port: url.port
|
|
620
|
+
? parseInt(url.port, 10)
|
|
621
|
+
: this.getDefaultPort(dialect),
|
|
614
622
|
database: url.pathname.replace(/^\//, ''),
|
|
615
623
|
username: url.username || undefined,
|
|
616
624
|
password: url.password || undefined,
|
|
617
625
|
ssl,
|
|
618
626
|
pool: {
|
|
619
|
-
max: searchParams.get('pool_max')
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
627
|
+
max: searchParams.get('pool_max')
|
|
628
|
+
? parseInt(searchParams.get('pool_max'), 10)
|
|
629
|
+
: 10,
|
|
630
|
+
min: searchParams.get('pool_min')
|
|
631
|
+
? parseInt(searchParams.get('pool_min'), 10)
|
|
632
|
+
: 0,
|
|
633
|
+
},
|
|
634
|
+
},
|
|
623
635
|
};
|
|
624
636
|
}
|
|
625
637
|
return {
|
|
@@ -630,14 +642,15 @@ export class NOORMME {
|
|
|
630
642
|
database: url.pathname.slice(1), // Remove leading slash
|
|
631
643
|
username: url.username || '',
|
|
632
644
|
password: url.password || '',
|
|
633
|
-
ssl: url.searchParams.get('ssl') === 'true' ||
|
|
634
|
-
|
|
645
|
+
ssl: url.searchParams.get('ssl') === 'true' ||
|
|
646
|
+
url.searchParams.get('sslmode') === 'require',
|
|
647
|
+
},
|
|
635
648
|
};
|
|
636
649
|
}
|
|
637
650
|
catch (error) {
|
|
638
651
|
throw new NoormError(`Failed to parse connection string: ${error instanceof Error ? error.message : String(error)}`, {
|
|
639
652
|
operation: 'connection_string_parsing',
|
|
640
|
-
suggestion: 'Ensure connection string format is: protocol://username:password@host:port/database'
|
|
653
|
+
suggestion: 'Ensure connection string format is: protocol://username:password@host:port/database',
|
|
641
654
|
});
|
|
642
655
|
}
|
|
643
656
|
}
|
|
@@ -646,10 +659,14 @@ export class NOORMME {
|
|
|
646
659
|
*/
|
|
647
660
|
getDefaultPort(dialect) {
|
|
648
661
|
switch (dialect) {
|
|
649
|
-
case 'sqlite':
|
|
650
|
-
|
|
651
|
-
case '
|
|
652
|
-
|
|
662
|
+
case 'sqlite':
|
|
663
|
+
return 0;
|
|
664
|
+
case 'postgresql':
|
|
665
|
+
return 5432;
|
|
666
|
+
case 'mysql':
|
|
667
|
+
return 3306;
|
|
668
|
+
default:
|
|
669
|
+
return 0;
|
|
653
670
|
}
|
|
654
671
|
}
|
|
655
672
|
createDialect() {
|
|
@@ -657,7 +674,7 @@ export class NOORMME {
|
|
|
657
674
|
switch (dialect) {
|
|
658
675
|
case 'sqlite':
|
|
659
676
|
return new SqliteDialect({
|
|
660
|
-
database: new Database(connection.database)
|
|
677
|
+
database: new Database(connection.database),
|
|
661
678
|
});
|
|
662
679
|
case 'postgresql':
|
|
663
680
|
return new PostgresDialect({
|
|
@@ -671,7 +688,7 @@ export class NOORMME {
|
|
|
671
688
|
max: connection.pool?.max ?? 10,
|
|
672
689
|
min: connection.pool?.min ?? 0,
|
|
673
690
|
idleTimeoutMillis: connection.pool?.idleTimeoutMillis ?? 10000,
|
|
674
|
-
}
|
|
691
|
+
},
|
|
675
692
|
});
|
|
676
693
|
default:
|
|
677
694
|
throw new Error(`Unsupported dialect: ${dialect}`);
|
|
@@ -19,7 +19,7 @@ export const defaultPerformanceConfig = {
|
|
|
19
19
|
maxSize: 1000,
|
|
20
20
|
defaultTtl: 300000, // 5 minutes
|
|
21
21
|
cleanupInterval: 60000, // 1 minute
|
|
22
|
-
enableMetrics: true
|
|
22
|
+
enableMetrics: true,
|
|
23
23
|
},
|
|
24
24
|
metrics: {
|
|
25
25
|
enabled: true,
|
|
@@ -28,14 +28,14 @@ export const defaultPerformanceConfig = {
|
|
|
28
28
|
missingIndexDetection: true,
|
|
29
29
|
largeResultSetThreshold: 1000,
|
|
30
30
|
maxHistorySize: 10000,
|
|
31
|
-
warningRetentionDays: 7
|
|
31
|
+
warningRetentionDays: 7,
|
|
32
32
|
},
|
|
33
33
|
connectionPool: {
|
|
34
34
|
minConnections: 2,
|
|
35
35
|
maxConnections: 10,
|
|
36
36
|
acquireTimeout: 30000,
|
|
37
37
|
idleTimeout: 300000,
|
|
38
|
-
validationInterval: 60000
|
|
38
|
+
validationInterval: 60000,
|
|
39
39
|
},
|
|
40
40
|
optimizer: {
|
|
41
41
|
enableQueryCache: true,
|
|
@@ -43,6 +43,6 @@ export const defaultPerformanceConfig = {
|
|
|
43
43
|
enableQueryRewriting: true,
|
|
44
44
|
slowQueryThreshold: 1000,
|
|
45
45
|
cacheSize: 1000,
|
|
46
|
-
maxCacheAge: 300000
|
|
47
|
-
}
|
|
46
|
+
maxCacheAge: 300000,
|
|
47
|
+
},
|
|
48
48
|
};
|
|
@@ -25,20 +25,20 @@ export class QueryOptimizer {
|
|
|
25
25
|
slowQueryThreshold: 1000,
|
|
26
26
|
cacheSize: 1000,
|
|
27
27
|
maxCacheAge: 300000,
|
|
28
|
-
...options
|
|
28
|
+
...options,
|
|
29
29
|
};
|
|
30
30
|
// Initialize services
|
|
31
31
|
this.cacheService = new QueryCacheService({
|
|
32
32
|
maxSize: this.options.cacheSize,
|
|
33
33
|
defaultTtl: this.options.maxCacheAge,
|
|
34
|
-
enableMetrics: true
|
|
34
|
+
enableMetrics: true,
|
|
35
35
|
}, this.logger);
|
|
36
36
|
this.metricsCollector = new MetricsCollector({
|
|
37
37
|
enabled: true,
|
|
38
38
|
slowQueryThreshold: this.options.slowQueryThreshold,
|
|
39
39
|
nPlusOneDetection: true,
|
|
40
40
|
missingIndexDetection: this.options.enableIndexRecommendations,
|
|
41
|
-
largeResultSetThreshold: 1000
|
|
41
|
+
largeResultSetThreshold: 1000,
|
|
42
42
|
}, this.logger);
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
@@ -59,7 +59,7 @@ export class QueryOptimizer {
|
|
|
59
59
|
executionTime,
|
|
60
60
|
improvement: 100,
|
|
61
61
|
suggestions: ['Query served from cache'],
|
|
62
|
-
result: cachedResult
|
|
62
|
+
result: cachedResult,
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
65
|
}
|
|
@@ -79,7 +79,7 @@ export class QueryOptimizer {
|
|
|
79
79
|
this.metricsCollector.recordQuery(query, executionTime, {
|
|
80
80
|
table: context?.table,
|
|
81
81
|
operation: context?.operation,
|
|
82
|
-
resultCount: Array.isArray(result) ? result.length : 1
|
|
82
|
+
resultCount: Array.isArray(result) ? result.length : 1,
|
|
83
83
|
});
|
|
84
84
|
// Generate suggestions
|
|
85
85
|
const suggestions = this.generateSuggestions(parsedQuery, executionTime, context);
|
|
@@ -90,7 +90,7 @@ export class QueryOptimizer {
|
|
|
90
90
|
executionTime,
|
|
91
91
|
improvement: optimization.improvement,
|
|
92
92
|
suggestions,
|
|
93
|
-
result
|
|
93
|
+
result,
|
|
94
94
|
};
|
|
95
95
|
}
|
|
96
96
|
catch (error) {
|
|
@@ -100,11 +100,11 @@ export class QueryOptimizer {
|
|
|
100
100
|
this.metricsCollector.recordQuery(query, executionTime, {
|
|
101
101
|
table: context?.table,
|
|
102
102
|
operation: context?.operation,
|
|
103
|
-
error: errorMessage
|
|
103
|
+
error: errorMessage,
|
|
104
104
|
});
|
|
105
105
|
this.logger.error(`Query optimization failed: ${errorMessage}`, {
|
|
106
106
|
query,
|
|
107
|
-
executionTime
|
|
107
|
+
executionTime,
|
|
108
108
|
});
|
|
109
109
|
throw error;
|
|
110
110
|
}
|
|
@@ -134,7 +134,7 @@ export class QueryOptimizer {
|
|
|
134
134
|
return {
|
|
135
135
|
...metricsStats,
|
|
136
136
|
cache: cacheStats,
|
|
137
|
-
indexRecommendations: 0 // Would be populated by recommendations
|
|
137
|
+
indexRecommendations: 0, // Would be populated by recommendations
|
|
138
138
|
};
|
|
139
139
|
}
|
|
140
140
|
/**
|
|
@@ -195,7 +195,7 @@ export class QueryOptimizer {
|
|
|
195
195
|
return {
|
|
196
196
|
optimizedQuery,
|
|
197
197
|
type,
|
|
198
|
-
improvement
|
|
198
|
+
improvement,
|
|
199
199
|
};
|
|
200
200
|
}
|
|
201
201
|
/**
|
|
@@ -205,7 +205,8 @@ export class QueryOptimizer {
|
|
|
205
205
|
let optimizedQuery = originalQuery;
|
|
206
206
|
let improvement = 0;
|
|
207
207
|
// Add LIMIT if missing and query could return many rows
|
|
208
|
-
if (!parsedQuery.hasLimit &&
|
|
208
|
+
if (!parsedQuery.hasLimit &&
|
|
209
|
+
QueryParser.couldReturnManyRows(originalQuery)) {
|
|
209
210
|
optimizedQuery = `${originalQuery} LIMIT 1000`;
|
|
210
211
|
improvement = 10;
|
|
211
212
|
}
|
|
@@ -219,7 +220,7 @@ export class QueryOptimizer {
|
|
|
219
220
|
}
|
|
220
221
|
return {
|
|
221
222
|
optimizedQuery,
|
|
222
|
-
improvement
|
|
223
|
+
improvement,
|
|
223
224
|
};
|
|
224
225
|
}
|
|
225
226
|
/**
|
|
@@ -244,13 +245,14 @@ export class QueryOptimizer {
|
|
|
244
245
|
// Check for missing indexes on GROUP BY columns
|
|
245
246
|
if (parsedQuery.hasAggregates && parsedQuery.groupByColumns.length > 0) {
|
|
246
247
|
const table = parsedQuery.tables[0];
|
|
247
|
-
if (table &&
|
|
248
|
+
if (table &&
|
|
249
|
+
parsedQuery.groupByColumns.every((col) => this.hasIndexOnColumn(table, col))) {
|
|
248
250
|
improvement = Math.max(improvement, 25);
|
|
249
251
|
}
|
|
250
252
|
}
|
|
251
253
|
return {
|
|
252
254
|
optimizedQuery,
|
|
253
|
-
improvement
|
|
255
|
+
improvement,
|
|
254
256
|
};
|
|
255
257
|
}
|
|
256
258
|
/**
|
|
@@ -271,7 +273,7 @@ export class QueryOptimizer {
|
|
|
271
273
|
type: 'btree',
|
|
272
274
|
reason: `WHERE clause on ${column}`,
|
|
273
275
|
estimatedImprovement: 20,
|
|
274
|
-
priority: 'medium'
|
|
276
|
+
priority: 'medium',
|
|
275
277
|
});
|
|
276
278
|
}
|
|
277
279
|
}
|
|
@@ -284,7 +286,7 @@ export class QueryOptimizer {
|
|
|
284
286
|
type: 'btree',
|
|
285
287
|
reason: `JOIN condition on ${column}`,
|
|
286
288
|
estimatedImprovement: 30,
|
|
287
|
-
priority: 'high'
|
|
289
|
+
priority: 'high',
|
|
288
290
|
});
|
|
289
291
|
}
|
|
290
292
|
}
|
|
@@ -297,7 +299,7 @@ export class QueryOptimizer {
|
|
|
297
299
|
type: 'btree',
|
|
298
300
|
reason: `ORDER BY clause on ${column}`,
|
|
299
301
|
estimatedImprovement: 15,
|
|
300
|
-
priority: 'medium'
|
|
302
|
+
priority: 'medium',
|
|
301
303
|
});
|
|
302
304
|
}
|
|
303
305
|
}
|
|
@@ -356,7 +358,10 @@ export class QueryOptimizer {
|
|
|
356
358
|
}
|
|
357
359
|
catch (error) {
|
|
358
360
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
359
|
-
this.logger.error(`Query execution failed: ${errorMessage}`, {
|
|
361
|
+
this.logger.error(`Query execution failed: ${errorMessage}`, {
|
|
362
|
+
query,
|
|
363
|
+
params,
|
|
364
|
+
});
|
|
360
365
|
throw error;
|
|
361
366
|
}
|
|
362
367
|
}
|
|
@@ -364,15 +369,15 @@ export class QueryOptimizer {
|
|
|
364
369
|
* Check if column has an index
|
|
365
370
|
*/
|
|
366
371
|
hasIndexOnColumn(table, column) {
|
|
367
|
-
const tableInfo = this.schemaInfo.tables.find(t => t.name === table);
|
|
372
|
+
const tableInfo = this.schemaInfo.tables.find((t) => t.name === table);
|
|
368
373
|
if (!tableInfo)
|
|
369
374
|
return false;
|
|
370
375
|
// Check if column is primary key
|
|
371
|
-
const columnInfo = tableInfo.columns.find(col => col.name === column);
|
|
376
|
+
const columnInfo = tableInfo.columns.find((col) => col.name === column);
|
|
372
377
|
if (columnInfo?.isPrimaryKey)
|
|
373
378
|
return true;
|
|
374
379
|
// Check if column has an index
|
|
375
|
-
return tableInfo.indexes.some(idx => idx.columns.includes(column));
|
|
380
|
+
return tableInfo.indexes.some((idx) => idx.columns.includes(column));
|
|
376
381
|
}
|
|
377
382
|
}
|
|
378
383
|
/**
|
|
@@ -18,7 +18,7 @@ export class CacheService {
|
|
|
18
18
|
cleanupInterval: 60000, // 1 minute
|
|
19
19
|
enableCompression: false,
|
|
20
20
|
enableMetrics: true,
|
|
21
|
-
...config
|
|
21
|
+
...config,
|
|
22
22
|
};
|
|
23
23
|
this.stats = {
|
|
24
24
|
size: 0,
|
|
@@ -28,25 +28,25 @@ export class CacheService {
|
|
|
28
28
|
hitRate: 0,
|
|
29
29
|
totalSize: 0,
|
|
30
30
|
evictions: 0,
|
|
31
|
-
lastCleanup: new Date()
|
|
31
|
+
lastCleanup: new Date(),
|
|
32
32
|
};
|
|
33
33
|
this.metrics = {
|
|
34
34
|
operations: {
|
|
35
35
|
get: 0,
|
|
36
36
|
set: 0,
|
|
37
37
|
delete: 0,
|
|
38
|
-
clear: 0
|
|
38
|
+
clear: 0,
|
|
39
39
|
},
|
|
40
40
|
performance: {
|
|
41
41
|
averageGetTime: 0,
|
|
42
42
|
averageSetTime: 0,
|
|
43
|
-
slowestOperation: 0
|
|
43
|
+
slowestOperation: 0,
|
|
44
44
|
},
|
|
45
45
|
memory: {
|
|
46
46
|
totalSize: 0,
|
|
47
47
|
averageEntrySize: 0,
|
|
48
|
-
largestEntry: 0
|
|
49
|
-
}
|
|
48
|
+
largestEntry: 0,
|
|
49
|
+
},
|
|
50
50
|
};
|
|
51
51
|
this.startCleanupTimer();
|
|
52
52
|
}
|
|
@@ -103,7 +103,7 @@ export class CacheService {
|
|
|
103
103
|
timestamp: Date.now(),
|
|
104
104
|
ttl: entryTtl,
|
|
105
105
|
hitCount: 0,
|
|
106
|
-
size: entrySize
|
|
106
|
+
size: entrySize,
|
|
107
107
|
};
|
|
108
108
|
this.cache.set(key, entry);
|
|
109
109
|
this.updateStats();
|
|
@@ -189,7 +189,10 @@ export class CacheService {
|
|
|
189
189
|
* Get cache entries (for debugging)
|
|
190
190
|
*/
|
|
191
191
|
entries() {
|
|
192
|
-
return Array.from(this.cache.entries()).map(([key, entry]) => ({
|
|
192
|
+
return Array.from(this.cache.entries()).map(([key, entry]) => ({
|
|
193
|
+
key,
|
|
194
|
+
entry,
|
|
195
|
+
}));
|
|
193
196
|
}
|
|
194
197
|
/**
|
|
195
198
|
* Warm cache with multiple entries
|
|
@@ -216,19 +219,23 @@ export class CacheService {
|
|
|
216
219
|
recommendations.push('Consider increasing TTL or cache size');
|
|
217
220
|
}
|
|
218
221
|
// Check memory usage
|
|
219
|
-
if (this.stats.totalSize > 100 * 1024 * 1024) {
|
|
222
|
+
if (this.stats.totalSize > 100 * 1024 * 1024) {
|
|
223
|
+
// 100MB
|
|
220
224
|
issues.push(`High memory usage: ${(this.stats.totalSize / 1024 / 1024).toFixed(1)}MB`);
|
|
221
225
|
recommendations.push('Consider reducing cache size or enabling compression');
|
|
222
226
|
}
|
|
223
227
|
// Check eviction rate
|
|
224
|
-
const evictionRate = this.stats.evictions /
|
|
228
|
+
const evictionRate = this.stats.evictions /
|
|
229
|
+
Math.max(this.stats.hitCount + this.stats.missCount, 1);
|
|
225
230
|
if (evictionRate > 0.1) {
|
|
226
231
|
issues.push(`High eviction rate: ${(evictionRate * 100).toFixed(1)}%`);
|
|
227
232
|
recommendations.push('Consider increasing cache size');
|
|
228
233
|
}
|
|
229
234
|
let status = 'healthy';
|
|
230
235
|
if (issues.length > 0) {
|
|
231
|
-
status = issues.some(issue => issue.includes('critical'))
|
|
236
|
+
status = issues.some((issue) => issue.includes('critical'))
|
|
237
|
+
? 'critical'
|
|
238
|
+
: 'warning';
|
|
232
239
|
}
|
|
233
240
|
return { status, issues, recommendations };
|
|
234
241
|
}
|
|
@@ -297,7 +304,8 @@ export class CacheService {
|
|
|
297
304
|
this.stats.totalSize = totalSize;
|
|
298
305
|
this.metrics.memory.totalSize = totalSize;
|
|
299
306
|
this.metrics.memory.largestEntry = largestEntry;
|
|
300
|
-
this.metrics.memory.averageEntrySize =
|
|
307
|
+
this.metrics.memory.averageEntrySize =
|
|
308
|
+
this.cache.size > 0 ? totalSize / this.cache.size : 0;
|
|
301
309
|
}
|
|
302
310
|
/**
|
|
303
311
|
* Update hit rate
|
|
@@ -316,12 +324,14 @@ export class CacheService {
|
|
|
316
324
|
if (operation === 'get') {
|
|
317
325
|
const totalGets = this.metrics.operations.get;
|
|
318
326
|
this.metrics.performance.averageGetTime =
|
|
319
|
-
(this.metrics.performance.averageGetTime * (totalGets - 1) + duration) /
|
|
327
|
+
(this.metrics.performance.averageGetTime * (totalGets - 1) + duration) /
|
|
328
|
+
totalGets;
|
|
320
329
|
}
|
|
321
330
|
else if (operation === 'set') {
|
|
322
331
|
const totalSets = this.metrics.operations.set;
|
|
323
332
|
this.metrics.performance.averageSetTime =
|
|
324
|
-
(this.metrics.performance.averageSetTime * (totalSets - 1) + duration) /
|
|
333
|
+
(this.metrics.performance.averageSetTime * (totalSets - 1) + duration) /
|
|
334
|
+
totalSets;
|
|
325
335
|
}
|
|
326
336
|
}
|
|
327
337
|
/**
|
|
@@ -367,7 +377,7 @@ export class QueryCacheService extends CacheService {
|
|
|
367
377
|
defaultTtl: 300000, // 5 minutes
|
|
368
378
|
cleanupInterval: 60000, // 1 minute
|
|
369
379
|
enableMetrics: true,
|
|
370
|
-
...config
|
|
380
|
+
...config,
|
|
371
381
|
}, logger);
|
|
372
382
|
}
|
|
373
383
|
/**
|
|
@@ -389,7 +399,7 @@ export class QueryCacheService extends CacheService {
|
|
|
389
399
|
*/
|
|
390
400
|
generateQueryKey(query, params) {
|
|
391
401
|
const normalizedQuery = query.replace(/\s+/g, ' ').trim();
|
|
392
|
-
const paramsKey = params.map(p => String(p)).join('|');
|
|
402
|
+
const paramsKey = params.map((p) => String(p)).join('|');
|
|
393
403
|
return `query:${normalizedQuery}:${paramsKey}`;
|
|
394
404
|
}
|
|
395
405
|
/**
|