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
|
@@ -19,7 +19,7 @@ class ConnectionFactory {
|
|
|
19
19
|
activeConnections: 0,
|
|
20
20
|
failedCreations: 0,
|
|
21
21
|
averageCreationTime: 0,
|
|
22
|
-
averageValidationTime: 0
|
|
22
|
+
averageValidationTime: 0,
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
@@ -39,7 +39,7 @@ class ConnectionFactory {
|
|
|
39
39
|
lastUsed: new Date(),
|
|
40
40
|
isActive: true,
|
|
41
41
|
inUse: false,
|
|
42
|
-
config
|
|
42
|
+
config,
|
|
43
43
|
};
|
|
44
44
|
this.connections.set(id, connection);
|
|
45
45
|
this.updateStats('created', performance.now() - startTime);
|
|
@@ -63,7 +63,7 @@ class ConnectionFactory {
|
|
|
63
63
|
this.updateStats('validated', responseTime);
|
|
64
64
|
return {
|
|
65
65
|
isValid: true,
|
|
66
|
-
responseTime
|
|
66
|
+
responseTime,
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
69
|
catch (error) {
|
|
@@ -73,7 +73,7 @@ class ConnectionFactory {
|
|
|
73
73
|
return {
|
|
74
74
|
isValid: false,
|
|
75
75
|
error: errorMessage,
|
|
76
|
-
responseTime
|
|
76
|
+
responseTime,
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
79
|
}
|
|
@@ -93,13 +93,13 @@ class ConnectionFactory {
|
|
|
93
93
|
* Get active connections
|
|
94
94
|
*/
|
|
95
95
|
getActiveConnections() {
|
|
96
|
-
return Array.from(this.connections.values()).filter(conn => conn.isActive);
|
|
96
|
+
return Array.from(this.connections.values()).filter((conn) => conn.isActive);
|
|
97
97
|
}
|
|
98
98
|
/**
|
|
99
99
|
* Get idle connections
|
|
100
100
|
*/
|
|
101
101
|
getIdleConnections() {
|
|
102
|
-
return Array.from(this.connections.values()).filter(conn => conn.isActive && !conn.inUse);
|
|
102
|
+
return Array.from(this.connections.values()).filter((conn) => conn.isActive && !conn.inUse);
|
|
103
103
|
}
|
|
104
104
|
/**
|
|
105
105
|
* Mark connection as in use
|
|
@@ -140,7 +140,7 @@ class ConnectionFactory {
|
|
|
140
140
|
* Destroy all connections
|
|
141
141
|
*/
|
|
142
142
|
async destroyAllConnections() {
|
|
143
|
-
const destroyPromises = Array.from(this.connections.keys()).map(id => this.destroyConnection(id));
|
|
143
|
+
const destroyPromises = Array.from(this.connections.keys()).map((id) => this.destroyConnection(id));
|
|
144
144
|
await Promise.all(destroyPromises);
|
|
145
145
|
this.logger.info('Destroyed all connections');
|
|
146
146
|
}
|
|
@@ -151,8 +151,7 @@ class ConnectionFactory {
|
|
|
151
151
|
const now = Date.now();
|
|
152
152
|
let cleaned = 0;
|
|
153
153
|
for (const [id, connection] of this.connections.entries()) {
|
|
154
|
-
if (!connection.inUse &&
|
|
155
|
-
now - connection.lastUsed.getTime() > maxAge) {
|
|
154
|
+
if (!connection.inUse && now - connection.lastUsed.getTime() > maxAge) {
|
|
156
155
|
if (await this.destroyConnection(id)) {
|
|
157
156
|
cleaned++;
|
|
158
157
|
}
|
|
@@ -173,7 +172,7 @@ class ConnectionFactory {
|
|
|
173
172
|
id: connection.id,
|
|
174
173
|
isValid: result.isValid,
|
|
175
174
|
error: result.error,
|
|
176
|
-
responseTime: result.responseTime
|
|
175
|
+
responseTime: result.responseTime,
|
|
177
176
|
};
|
|
178
177
|
});
|
|
179
178
|
return Promise.all(validationPromises);
|
|
@@ -191,7 +190,7 @@ class ConnectionFactory {
|
|
|
191
190
|
const connections = this.getAllConnections();
|
|
192
191
|
const activeConnections = this.getActiveConnections();
|
|
193
192
|
const idleConnections = this.getIdleConnections();
|
|
194
|
-
const inUseConnections = connections.filter(c => c.inUse);
|
|
193
|
+
const inUseConnections = connections.filter((c) => c.inUse);
|
|
195
194
|
const issues = [];
|
|
196
195
|
// Check for failed creations
|
|
197
196
|
if (this.stats.failedCreations > 0) {
|
|
@@ -207,7 +206,9 @@ class ConnectionFactory {
|
|
|
207
206
|
}
|
|
208
207
|
let status = 'healthy';
|
|
209
208
|
if (issues.length > 0) {
|
|
210
|
-
status = issues.some(issue => issue.includes('failures'))
|
|
209
|
+
status = issues.some((issue) => issue.includes('failures'))
|
|
210
|
+
? 'critical'
|
|
211
|
+
: 'warning';
|
|
211
212
|
}
|
|
212
213
|
return {
|
|
213
214
|
status,
|
|
@@ -216,8 +217,8 @@ class ConnectionFactory {
|
|
|
216
217
|
total: connections.length,
|
|
217
218
|
active: activeConnections.length,
|
|
218
219
|
idle: idleConnections.length,
|
|
219
|
-
inUse: inUseConnections.length
|
|
220
|
-
}
|
|
220
|
+
inUse: inUseConnections.length,
|
|
221
|
+
},
|
|
221
222
|
};
|
|
222
223
|
}
|
|
223
224
|
/**
|
|
@@ -286,7 +287,7 @@ class ConnectionPoolManager {
|
|
|
286
287
|
acquireTimeout: 30000,
|
|
287
288
|
idleTimeout: 300000,
|
|
288
289
|
validationInterval: 60000,
|
|
289
|
-
...poolConfig
|
|
290
|
+
...poolConfig,
|
|
290
291
|
};
|
|
291
292
|
this.startValidationTimer();
|
|
292
293
|
}
|
|
@@ -297,7 +298,7 @@ class ConnectionPoolManager {
|
|
|
297
298
|
this.logger.info(`Initializing connection pool with ${this.poolConfig.minConnections} minimum connections`);
|
|
298
299
|
const initPromises = Array.from({ length: this.poolConfig.minConnections }, (_, i) => this.factory.createConnection({
|
|
299
300
|
...this.config,
|
|
300
|
-
id: `pool_conn_${i}
|
|
301
|
+
id: `pool_conn_${i}`,
|
|
301
302
|
}));
|
|
302
303
|
try {
|
|
303
304
|
await Promise.all(initPromises);
|
|
@@ -329,7 +330,7 @@ class ConnectionPoolManager {
|
|
|
329
330
|
if (currentConnections.length < this.poolConfig.maxConnections) {
|
|
330
331
|
const newConnection = await this.factory.createConnection({
|
|
331
332
|
...this.config,
|
|
332
|
-
id: `pool_conn_${Date.now()}
|
|
333
|
+
id: `pool_conn_${Date.now()}`,
|
|
333
334
|
});
|
|
334
335
|
this.factory.markInUse(newConnection);
|
|
335
336
|
this.logger.debug(`Created and acquired new connection ${newConnection.id}`);
|
|
@@ -385,8 +386,8 @@ class ConnectionPoolManager {
|
|
|
385
386
|
...factoryStats,
|
|
386
387
|
poolSize: connections.length,
|
|
387
388
|
idleConnections: this.factory.getIdleConnections().length,
|
|
388
|
-
inUseConnections: connections.filter(c => c.inUse).length,
|
|
389
|
-
waitingQueue: this.waitingQueue.length
|
|
389
|
+
inUseConnections: connections.filter((c) => c.inUse).length,
|
|
390
|
+
waitingQueue: this.waitingQueue.length,
|
|
390
391
|
};
|
|
391
392
|
}
|
|
392
393
|
/**
|
|
@@ -421,7 +422,7 @@ class ConnectionPoolManager {
|
|
|
421
422
|
async waitForConnection(startTime) {
|
|
422
423
|
return new Promise((resolve, reject) => {
|
|
423
424
|
const timeout = setTimeout(() => {
|
|
424
|
-
const index = this.waitingQueue.findIndex(item => item.reject === reject);
|
|
425
|
+
const index = this.waitingQueue.findIndex((item) => item.reject === reject);
|
|
425
426
|
if (index !== -1) {
|
|
426
427
|
this.waitingQueue.splice(index, 1);
|
|
427
428
|
}
|
|
@@ -436,7 +437,7 @@ class ConnectionPoolManager {
|
|
|
436
437
|
clearTimeout(timeout);
|
|
437
438
|
reject(error);
|
|
438
439
|
},
|
|
439
|
-
timestamp: Date.now()
|
|
440
|
+
timestamp: Date.now(),
|
|
440
441
|
});
|
|
441
442
|
});
|
|
442
443
|
}
|
|
@@ -466,7 +467,9 @@ class ConnectionPoolManager {
|
|
|
466
467
|
* Validate all connections in the pool
|
|
467
468
|
*/
|
|
468
469
|
async validateConnections() {
|
|
469
|
-
const validationPromises = this.factory
|
|
470
|
+
const validationPromises = this.factory
|
|
471
|
+
.getIdleConnections()
|
|
472
|
+
.map(async (connection) => {
|
|
470
473
|
const validation = await this.factory.validateConnection(connection);
|
|
471
474
|
if (!validation.isValid) {
|
|
472
475
|
await this.factory.destroyConnection(connection.id);
|
|
@@ -480,7 +483,9 @@ class ConnectionPoolManager {
|
|
|
480
483
|
async cleanupIdleConnections() {
|
|
481
484
|
const now = Date.now();
|
|
482
485
|
const idleConnections = this.factory.getIdleConnections();
|
|
483
|
-
const excessConnections = idleConnections
|
|
486
|
+
const excessConnections = idleConnections
|
|
487
|
+
.filter((conn) => now - conn.lastUsed.getTime() > this.poolConfig.idleTimeout)
|
|
488
|
+
.slice(this.poolConfig.minConnections);
|
|
484
489
|
for (const connection of excessConnections) {
|
|
485
490
|
await this.factory.destroyConnection(connection.id);
|
|
486
491
|
}
|
|
@@ -59,11 +59,11 @@ class MetricsCollector {
|
|
|
59
59
|
maxHistorySize: 10000,
|
|
60
60
|
warningRetentionDays: 7,
|
|
61
61
|
persistPath: config.persistPath,
|
|
62
|
-
...config
|
|
62
|
+
...config,
|
|
63
63
|
};
|
|
64
64
|
this.startCleanupTimer();
|
|
65
65
|
// Attempt to load metrics on startup (fire and forget)
|
|
66
|
-
this.load().catch(err => this.logger.warn('Failed to load metrics:', err));
|
|
66
|
+
this.load().catch((err) => this.logger.warn('Failed to load metrics:', err));
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
69
69
|
* Load metrics from disk
|
|
@@ -101,7 +101,7 @@ class MetricsCollector {
|
|
|
101
101
|
const data = JSON.stringify({
|
|
102
102
|
queryHistory: this.queryHistory,
|
|
103
103
|
warnings: this.warnings,
|
|
104
|
-
savedAt: Date.now()
|
|
104
|
+
savedAt: Date.now(),
|
|
105
105
|
}, null, 2);
|
|
106
106
|
await fs.writeFile(this.config.persistPath, data, 'utf-8');
|
|
107
107
|
this.logger.debug(`Saved metrics to ${this.config.persistPath}`);
|
|
@@ -123,7 +123,7 @@ class MetricsCollector {
|
|
|
123
123
|
table: options.table,
|
|
124
124
|
operation: options.operation,
|
|
125
125
|
resultCount: options.resultCount,
|
|
126
|
-
error: options.error
|
|
126
|
+
error: options.error,
|
|
127
127
|
};
|
|
128
128
|
this.queryHistory.push(metrics);
|
|
129
129
|
// Keep history size under control
|
|
@@ -140,12 +140,13 @@ class MetricsCollector {
|
|
|
140
140
|
*/
|
|
141
141
|
getPerformanceStats() {
|
|
142
142
|
const totalQueries = this.queryHistory.length;
|
|
143
|
-
const slowQueries = this.queryHistory.filter(q => q.executionTime > this.config.slowQueryThreshold).length;
|
|
143
|
+
const slowQueries = this.queryHistory.filter((q) => q.executionTime > this.config.slowQueryThreshold).length;
|
|
144
144
|
const averageExecutionTime = totalQueries > 0
|
|
145
|
-
? this.queryHistory.reduce((sum, q) => sum + q.executionTime, 0) /
|
|
145
|
+
? this.queryHistory.reduce((sum, q) => sum + q.executionTime, 0) /
|
|
146
|
+
totalQueries
|
|
146
147
|
: 0;
|
|
147
148
|
const errorRate = totalQueries > 0
|
|
148
|
-
? this.queryHistory.filter(q => q.error).length / totalQueries
|
|
149
|
+
? this.queryHistory.filter((q) => q.error).length / totalQueries
|
|
149
150
|
: 0;
|
|
150
151
|
const warningCount = {};
|
|
151
152
|
for (const warning of this.warnings) {
|
|
@@ -160,7 +161,7 @@ class MetricsCollector {
|
|
|
160
161
|
errorRate,
|
|
161
162
|
warningCount,
|
|
162
163
|
topSlowQueries,
|
|
163
|
-
queryPatterns
|
|
164
|
+
queryPatterns,
|
|
164
165
|
};
|
|
165
166
|
}
|
|
166
167
|
/**
|
|
@@ -175,14 +176,13 @@ class MetricsCollector {
|
|
|
175
176
|
* Get warnings by type
|
|
176
177
|
*/
|
|
177
178
|
getWarningsByType(type) {
|
|
178
|
-
return this.warnings.filter(w => w.type === type);
|
|
179
|
+
return this.warnings.filter((w) => w.type === type);
|
|
179
180
|
}
|
|
180
181
|
/**
|
|
181
182
|
* Get query history
|
|
182
183
|
*/
|
|
183
184
|
getQueryHistory(limit) {
|
|
184
|
-
const history = this.queryHistory
|
|
185
|
-
.sort((a, b) => b.timestamp - a.timestamp);
|
|
185
|
+
const history = this.queryHistory.sort((a, b) => b.timestamp - a.timestamp);
|
|
186
186
|
return limit ? history.slice(0, limit) : history;
|
|
187
187
|
}
|
|
188
188
|
/**
|
|
@@ -191,7 +191,7 @@ class MetricsCollector {
|
|
|
191
191
|
getSlowQueries(threshold) {
|
|
192
192
|
const actualThreshold = threshold || this.config.slowQueryThreshold;
|
|
193
193
|
return this.queryHistory
|
|
194
|
-
.filter(q => q.executionTime > actualThreshold)
|
|
194
|
+
.filter((q) => q.executionTime > actualThreshold)
|
|
195
195
|
.sort((a, b) => b.executionTime - a.executionTime);
|
|
196
196
|
}
|
|
197
197
|
/**
|
|
@@ -216,7 +216,7 @@ class MetricsCollector {
|
|
|
216
216
|
let maxCountInWindow = 0;
|
|
217
217
|
for (const query of queries) {
|
|
218
218
|
const windowStart = query.timestamp - windowMs;
|
|
219
|
-
const countInWindow = queries.filter(q => q.timestamp >= windowStart && q.timestamp <= query.timestamp).length;
|
|
219
|
+
const countInWindow = queries.filter((q) => q.timestamp >= windowStart && q.timestamp <= query.timestamp).length;
|
|
220
220
|
maxCountInWindow = Math.max(maxCountInWindow, countInWindow);
|
|
221
221
|
}
|
|
222
222
|
if (maxCountInWindow >= 5) {
|
|
@@ -229,7 +229,7 @@ class MetricsCollector {
|
|
|
229
229
|
pattern,
|
|
230
230
|
count: maxCountInWindow,
|
|
231
231
|
timeWindow: windowMs,
|
|
232
|
-
severity
|
|
232
|
+
severity,
|
|
233
233
|
});
|
|
234
234
|
break;
|
|
235
235
|
}
|
|
@@ -255,7 +255,7 @@ class MetricsCollector {
|
|
|
255
255
|
config: this.config,
|
|
256
256
|
stats: this.getPerformanceStats(),
|
|
257
257
|
warnings: this.warnings,
|
|
258
|
-
queries: this.queryHistory
|
|
258
|
+
queries: this.queryHistory,
|
|
259
259
|
};
|
|
260
260
|
}
|
|
261
261
|
/**
|
|
@@ -280,7 +280,7 @@ class MetricsCollector {
|
|
|
280
280
|
// Clean up old recent queries (keep last 10 seconds)
|
|
281
281
|
const cutoff = Date.now() - 10000;
|
|
282
282
|
for (const [query, queries] of this.recentQueries.entries()) {
|
|
283
|
-
const recent = queries.filter(q => q.timestamp >= cutoff);
|
|
283
|
+
const recent = queries.filter((q) => q.timestamp >= cutoff);
|
|
284
284
|
if (recent.length === 0) {
|
|
285
285
|
this.recentQueries.delete(query);
|
|
286
286
|
}
|
|
@@ -302,8 +302,10 @@ class MetricsCollector {
|
|
|
302
302
|
suggestion: 'Consider adding indexes or optimizing the query',
|
|
303
303
|
query: metrics.query,
|
|
304
304
|
table: metrics.table,
|
|
305
|
-
severity: metrics.executionTime > this.config.slowQueryThreshold * 3
|
|
306
|
-
|
|
305
|
+
severity: metrics.executionTime > this.config.slowQueryThreshold * 3
|
|
306
|
+
? 'high'
|
|
307
|
+
: 'medium',
|
|
308
|
+
timestamp: Date.now(),
|
|
307
309
|
});
|
|
308
310
|
}
|
|
309
311
|
// Check for N+1 queries
|
|
@@ -314,15 +316,18 @@ class MetricsCollector {
|
|
|
314
316
|
}
|
|
315
317
|
}
|
|
316
318
|
// Check for large result sets
|
|
317
|
-
if (metrics.resultCount &&
|
|
319
|
+
if (metrics.resultCount &&
|
|
320
|
+
metrics.resultCount > this.config.largeResultSetThreshold) {
|
|
318
321
|
warnings.push({
|
|
319
322
|
type: 'large_result_set',
|
|
320
323
|
message: `Large result set: ${metrics.resultCount} rows returned`,
|
|
321
324
|
suggestion: 'Consider using pagination or filtering to reduce result size',
|
|
322
325
|
query: metrics.query,
|
|
323
326
|
table: metrics.table,
|
|
324
|
-
severity: metrics.resultCount > this.config.largeResultSetThreshold * 5
|
|
325
|
-
|
|
327
|
+
severity: metrics.resultCount > this.config.largeResultSetThreshold * 5
|
|
328
|
+
? 'high'
|
|
329
|
+
: 'medium',
|
|
330
|
+
timestamp: Date.now(),
|
|
326
331
|
});
|
|
327
332
|
}
|
|
328
333
|
// Log warnings
|
|
@@ -338,7 +343,7 @@ class MetricsCollector {
|
|
|
338
343
|
// Look for the same query executed multiple times in quick succession
|
|
339
344
|
if (recentQueries.length >= 5) {
|
|
340
345
|
const timeWindow = 5000; // 5 seconds
|
|
341
|
-
const recentInWindow = recentQueries.filter(q => Date.now() - q.timestamp < timeWindow);
|
|
346
|
+
const recentInWindow = recentQueries.filter((q) => Date.now() - q.timestamp < timeWindow);
|
|
342
347
|
if (recentInWindow.length >= 5) {
|
|
343
348
|
return {
|
|
344
349
|
type: 'n_plus_one',
|
|
@@ -347,7 +352,7 @@ class MetricsCollector {
|
|
|
347
352
|
query: metrics.query,
|
|
348
353
|
table: metrics.table,
|
|
349
354
|
severity: 'high',
|
|
350
|
-
timestamp: Date.now()
|
|
355
|
+
timestamp: Date.now(),
|
|
351
356
|
};
|
|
352
357
|
}
|
|
353
358
|
}
|
|
@@ -387,11 +392,11 @@ class MetricsCollector {
|
|
|
387
392
|
*/
|
|
388
393
|
getWarningEmoji(type) {
|
|
389
394
|
const emojis = {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
+
n_plus_one: '🔄',
|
|
396
|
+
missing_index: '📇',
|
|
397
|
+
slow_query: '🐌',
|
|
398
|
+
full_table_scan: '🔍',
|
|
399
|
+
large_result_set: '📊',
|
|
395
400
|
};
|
|
396
401
|
return emojis[type] || '⚠️';
|
|
397
402
|
}
|
|
@@ -425,7 +430,7 @@ class MetricsCollector {
|
|
|
425
430
|
.map(([query, { totalTime, count }]) => ({
|
|
426
431
|
query,
|
|
427
432
|
averageTime: totalTime / count,
|
|
428
|
-
count
|
|
433
|
+
count,
|
|
429
434
|
}))
|
|
430
435
|
.sort((a, b) => b.averageTime - a.averageTime)
|
|
431
436
|
.slice(0, 10);
|
|
@@ -447,7 +452,7 @@ class MetricsCollector {
|
|
|
447
452
|
.map(([pattern, { totalTime, count }]) => ({
|
|
448
453
|
pattern,
|
|
449
454
|
frequency: count,
|
|
450
|
-
averageTime: totalTime / count
|
|
455
|
+
averageTime: totalTime / count,
|
|
451
456
|
}))
|
|
452
457
|
.sort((a, b) => b.frequency - a.frequency)
|
|
453
458
|
.slice(0, 20);
|
|
@@ -458,22 +463,22 @@ class MetricsCollector {
|
|
|
458
463
|
startCleanupTimer() {
|
|
459
464
|
this.cleanupTimer = setInterval(() => {
|
|
460
465
|
this.cleanup();
|
|
461
|
-
this.save().catch(err => this.logger.warn('Failed to auto-save metrics:', err));
|
|
466
|
+
this.save().catch((err) => this.logger.warn('Failed to auto-save metrics:', err));
|
|
462
467
|
}, 60000); // Cleanup and save every minute
|
|
463
468
|
}
|
|
464
469
|
/**
|
|
465
470
|
* Cleanup old data
|
|
466
471
|
*/
|
|
467
472
|
cleanup() {
|
|
468
|
-
const cutoffTime = Date.now() -
|
|
473
|
+
const cutoffTime = Date.now() - this.config.warningRetentionDays * 24 * 60 * 60 * 1000;
|
|
469
474
|
// Remove old warnings
|
|
470
|
-
this.warnings = this.warnings.filter(w => w.timestamp > cutoffTime);
|
|
475
|
+
this.warnings = this.warnings.filter((w) => w.timestamp > cutoffTime);
|
|
471
476
|
// Remove old queries (keep last 24 hours)
|
|
472
|
-
const queryCutoff = Date.now() -
|
|
473
|
-
this.queryHistory = this.queryHistory.filter(q => q.timestamp > queryCutoff);
|
|
477
|
+
const queryCutoff = Date.now() - 24 * 60 * 60 * 1000;
|
|
478
|
+
this.queryHistory = this.queryHistory.filter((q) => q.timestamp > queryCutoff);
|
|
474
479
|
// Clean up recent queries
|
|
475
480
|
for (const [query, queries] of this.recentQueries.entries()) {
|
|
476
|
-
const recent = queries.filter(q => q.timestamp > queryCutoff);
|
|
481
|
+
const recent = queries.filter((q) => q.timestamp > queryCutoff);
|
|
477
482
|
if (recent.length === 0) {
|
|
478
483
|
this.recentQueries.delete(query);
|
|
479
484
|
}
|
|
@@ -23,7 +23,7 @@ class QueryParser {
|
|
|
23
23
|
groupByColumns: this.extractGroupByColumns(normalized),
|
|
24
24
|
hasLimit: lowerQuery.includes('limit'),
|
|
25
25
|
hasAggregates: this.hasAggregates(normalized),
|
|
26
|
-
isComplex: this.isComplexQuery(normalized)
|
|
26
|
+
isComplex: this.isComplexQuery(normalized),
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
@@ -60,7 +60,7 @@ class QueryParser {
|
|
|
60
60
|
// FROM clause
|
|
61
61
|
const fromMatches = query.match(/from\s+(\w+)/gi);
|
|
62
62
|
if (fromMatches) {
|
|
63
|
-
fromMatches.forEach(match => {
|
|
63
|
+
fromMatches.forEach((match) => {
|
|
64
64
|
const table = match.split(/\s+/)[1];
|
|
65
65
|
if (table)
|
|
66
66
|
tables.add(table);
|
|
@@ -69,7 +69,7 @@ class QueryParser {
|
|
|
69
69
|
// JOIN clauses
|
|
70
70
|
const joinMatches = query.match(/join\s+(\w+)/gi);
|
|
71
71
|
if (joinMatches) {
|
|
72
|
-
joinMatches.forEach(match => {
|
|
72
|
+
joinMatches.forEach((match) => {
|
|
73
73
|
const table = match.split(/\s+/)[1];
|
|
74
74
|
if (table)
|
|
75
75
|
tables.add(table);
|
|
@@ -87,7 +87,7 @@ class QueryParser {
|
|
|
87
87
|
const whereClause = whereMatch[1];
|
|
88
88
|
const columnMatches = whereClause.match(/(\w+)\s*[=<>!]/g);
|
|
89
89
|
return columnMatches
|
|
90
|
-
? columnMatches.map(match => match.split(/\s+/)[0]).filter(Boolean)
|
|
90
|
+
? columnMatches.map((match) => match.split(/\s+/)[0]).filter(Boolean)
|
|
91
91
|
: [];
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
@@ -116,7 +116,7 @@ class QueryParser {
|
|
|
116
116
|
return [];
|
|
117
117
|
return orderByMatch[1]
|
|
118
118
|
.split(',')
|
|
119
|
-
.map(col => col.trim().split(/\s+/)[0])
|
|
119
|
+
.map((col) => col.trim().split(/\s+/)[0])
|
|
120
120
|
.filter(Boolean);
|
|
121
121
|
}
|
|
122
122
|
/**
|
|
@@ -128,7 +128,7 @@ class QueryParser {
|
|
|
128
128
|
return [];
|
|
129
129
|
return groupByMatch[1]
|
|
130
130
|
.split(',')
|
|
131
|
-
.map(col => col.trim())
|
|
131
|
+
.map((col) => col.trim())
|
|
132
132
|
.filter(Boolean);
|
|
133
133
|
}
|
|
134
134
|
/**
|
|
@@ -136,25 +136,25 @@ class QueryParser {
|
|
|
136
136
|
*/
|
|
137
137
|
static hasAggregates(query) {
|
|
138
138
|
const lowerQuery = query.toLowerCase();
|
|
139
|
-
return lowerQuery.includes('group by') ||
|
|
139
|
+
return (lowerQuery.includes('group by') ||
|
|
140
140
|
lowerQuery.includes('having') ||
|
|
141
141
|
lowerQuery.includes('count(') ||
|
|
142
142
|
lowerQuery.includes('sum(') ||
|
|
143
143
|
lowerQuery.includes('avg(') ||
|
|
144
144
|
lowerQuery.includes('max(') ||
|
|
145
|
-
lowerQuery.includes('min(');
|
|
145
|
+
lowerQuery.includes('min('));
|
|
146
146
|
}
|
|
147
147
|
/**
|
|
148
148
|
* Check if query is complex (joins, subqueries, etc.)
|
|
149
149
|
*/
|
|
150
150
|
static isComplexQuery(query) {
|
|
151
151
|
const lowerQuery = query.toLowerCase();
|
|
152
|
-
return lowerQuery.includes('join') ||
|
|
152
|
+
return (lowerQuery.includes('join') ||
|
|
153
153
|
lowerQuery.includes('subquery') ||
|
|
154
154
|
lowerQuery.includes('union') ||
|
|
155
155
|
lowerQuery.includes('except') ||
|
|
156
156
|
lowerQuery.includes('intersect') ||
|
|
157
|
-
(lowerQuery.includes('select') && lowerQuery.includes('('));
|
|
157
|
+
(lowerQuery.includes('select') && lowerQuery.includes('(')));
|
|
158
158
|
}
|
|
159
159
|
/**
|
|
160
160
|
* Check if query could return many rows
|
|
@@ -193,7 +193,7 @@ class QueryParser {
|
|
|
193
193
|
*/
|
|
194
194
|
static generateCacheKey(query, params = []) {
|
|
195
195
|
const normalized = this.normalizeQuery(query);
|
|
196
|
-
const paramsKey = params.map(p => String(p)).join('|');
|
|
196
|
+
const paramsKey = params.map((p) => String(p)).join('|');
|
|
197
197
|
return `${normalized}:${paramsKey}`;
|
|
198
198
|
}
|
|
199
199
|
/**
|
|
@@ -239,12 +239,11 @@ class QueryParser {
|
|
|
239
239
|
original: query,
|
|
240
240
|
frequency: 1,
|
|
241
241
|
averageTime: executionTime,
|
|
242
|
-
tables: parsed.tables
|
|
242
|
+
tables: parsed.tables,
|
|
243
243
|
});
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
|
-
return Array.from(patternMap.values())
|
|
247
|
-
.sort((a, b) => b.frequency - a.frequency);
|
|
246
|
+
return Array.from(patternMap.values()).sort((a, b) => b.frequency - a.frequency);
|
|
248
247
|
}
|
|
249
248
|
/**
|
|
250
249
|
* Detect potential N+1 query patterns
|
|
@@ -270,7 +269,7 @@ class QueryParser {
|
|
|
270
269
|
let maxCountInWindow = 0;
|
|
271
270
|
for (const query of queries) {
|
|
272
271
|
const windowStart = query.timestamp - windowMs;
|
|
273
|
-
const countInWindow = queries.filter(q => q.timestamp >= windowStart && q.timestamp <= query.timestamp).length;
|
|
272
|
+
const countInWindow = queries.filter((q) => q.timestamp >= windowStart && q.timestamp <= query.timestamp).length;
|
|
274
273
|
maxCountInWindow = Math.max(maxCountInWindow, countInWindow);
|
|
275
274
|
}
|
|
276
275
|
if (maxCountInWindow >= 5) {
|
|
@@ -283,7 +282,7 @@ class QueryParser {
|
|
|
283
282
|
pattern,
|
|
284
283
|
count: maxCountInWindow,
|
|
285
284
|
timeWindow: windowMs,
|
|
286
|
-
severity
|
|
285
|
+
severity,
|
|
287
286
|
});
|
|
288
287
|
break; // Only report the most severe pattern
|
|
289
288
|
}
|
|
@@ -41,7 +41,7 @@ class RelationshipEngine {
|
|
|
41
41
|
*/
|
|
42
42
|
async loadEntityRelationships(entity, relations) {
|
|
43
43
|
for (const relationName of relations) {
|
|
44
|
-
const relationship = this.relationships.find(r => r.name === relationName);
|
|
44
|
+
const relationship = this.relationships.find((r) => r.name === relationName);
|
|
45
45
|
if (!relationship)
|
|
46
46
|
continue;
|
|
47
47
|
await this.loadSingleRelationship(entity, relationship);
|
|
@@ -52,7 +52,7 @@ class RelationshipEngine {
|
|
|
52
52
|
*/
|
|
53
53
|
async batchLoadRelationships(entities, relations) {
|
|
54
54
|
for (const relationName of relations) {
|
|
55
|
-
const relationship = this.relationships.find(r => r.name === relationName);
|
|
55
|
+
const relationship = this.relationships.find((r) => r.name === relationName);
|
|
56
56
|
if (!relationship)
|
|
57
57
|
continue;
|
|
58
58
|
await this.batchLoadSingleRelationship(entities, relationship);
|
|
@@ -85,6 +85,7 @@ class RelationshipEngine {
|
|
|
85
85
|
relatedData = await this.loadManyToManyRelationship(entity, relationship);
|
|
86
86
|
break;
|
|
87
87
|
}
|
|
88
|
+
;
|
|
88
89
|
entity[relationship.name] = relatedData;
|
|
89
90
|
}
|
|
90
91
|
/**
|
|
@@ -92,8 +93,8 @@ class RelationshipEngine {
|
|
|
92
93
|
*/
|
|
93
94
|
async batchLoadSingleRelationship(entities, relationship) {
|
|
94
95
|
const entityValues = entities
|
|
95
|
-
.map(e => e[relationship.fromColumn])
|
|
96
|
-
.filter(v => v !== undefined && v !== null);
|
|
96
|
+
.map((e) => e[relationship.fromColumn])
|
|
97
|
+
.filter((v) => v !== undefined && v !== null);
|
|
97
98
|
if (entityValues.length === 0)
|
|
98
99
|
return;
|
|
99
100
|
let relatedData;
|
|
@@ -138,6 +139,7 @@ class RelationshipEngine {
|
|
|
138
139
|
else {
|
|
139
140
|
entityRelatedData = groupedData.get(entityValue) || [];
|
|
140
141
|
}
|
|
142
|
+
;
|
|
141
143
|
entity[relationship.name] = entityRelatedData;
|
|
142
144
|
}
|
|
143
145
|
}
|
|
@@ -167,8 +169,8 @@ class RelationshipEngine {
|
|
|
167
169
|
throw new Error('Many-to-many relationship requires throughTable');
|
|
168
170
|
}
|
|
169
171
|
const entityValues = entities
|
|
170
|
-
.map(e => e[relationship.fromColumn])
|
|
171
|
-
.filter(v => v !== undefined && v !== null);
|
|
172
|
+
.map((e) => e[relationship.fromColumn])
|
|
173
|
+
.filter((v) => v !== undefined && v !== null);
|
|
172
174
|
if (entityValues.length === 0)
|
|
173
175
|
return [];
|
|
174
176
|
return await this.db
|
|
@@ -182,7 +184,7 @@ class RelationshipEngine {
|
|
|
182
184
|
* Get relationships for a specific table
|
|
183
185
|
*/
|
|
184
186
|
getRelationshipsForTable(tableName) {
|
|
185
|
-
return this.relationships.filter(r => r.fromTable === tableName);
|
|
187
|
+
return this.relationships.filter((r) => r.fromTable === tableName);
|
|
186
188
|
}
|
|
187
189
|
/**
|
|
188
190
|
* Get all relationships
|
|
@@ -200,7 +202,7 @@ class RelationshipEngine {
|
|
|
200
202
|
* Remove a relationship
|
|
201
203
|
*/
|
|
202
204
|
removeRelationship(relationshipName) {
|
|
203
|
-
this.relationships = this.relationships.filter(r => r.name !== relationshipName);
|
|
205
|
+
this.relationships = this.relationships.filter((r) => r.name !== relationshipName);
|
|
204
206
|
}
|
|
205
207
|
}
|
|
206
208
|
exports.RelationshipEngine = RelationshipEngine;
|