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
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,27 +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
|
|
554
|
+
...config.performance,
|
|
553
555
|
},
|
|
554
556
|
agentic: config.agentic,
|
|
555
|
-
automation: config.automation
|
|
557
|
+
automation: config.automation,
|
|
556
558
|
};
|
|
557
559
|
}
|
|
558
560
|
/**
|
|
@@ -576,7 +578,7 @@ export class NOORMME {
|
|
|
576
578
|
default:
|
|
577
579
|
throw new NoormError(`Unsupported database protocol: ${url.protocol}`, {
|
|
578
580
|
operation: 'connection_string_parsing',
|
|
579
|
-
suggestion: 'Supported protocols: sqlite, postgresql, postgres, mysql'
|
|
581
|
+
suggestion: 'Supported protocols: sqlite, postgresql, postgres, mysql',
|
|
580
582
|
});
|
|
581
583
|
}
|
|
582
584
|
if (dialect === 'sqlite') {
|
|
@@ -587,8 +589,8 @@ export class NOORMME {
|
|
|
587
589
|
host: '',
|
|
588
590
|
port: 0,
|
|
589
591
|
username: '',
|
|
590
|
-
password: ''
|
|
591
|
-
}
|
|
592
|
+
password: '',
|
|
593
|
+
},
|
|
592
594
|
};
|
|
593
595
|
}
|
|
594
596
|
if (dialect === 'postgresql' || dialect === 'mysql') {
|
|
@@ -605,23 +607,31 @@ export class NOORMME {
|
|
|
605
607
|
}
|
|
606
608
|
else {
|
|
607
609
|
// For other SSL modes, we'll need more configuration
|
|
608
|
-
ssl = {
|
|
610
|
+
ssl = {
|
|
611
|
+
rejectUnauthorized: sslParam !== 'allow' && sslParam !== 'prefer',
|
|
612
|
+
};
|
|
609
613
|
}
|
|
610
614
|
}
|
|
611
615
|
return {
|
|
612
616
|
dialect,
|
|
613
617
|
connection: {
|
|
614
618
|
host: url.hostname || 'localhost',
|
|
615
|
-
port: url.port
|
|
619
|
+
port: url.port
|
|
620
|
+
? parseInt(url.port, 10)
|
|
621
|
+
: this.getDefaultPort(dialect),
|
|
616
622
|
database: url.pathname.replace(/^\//, ''),
|
|
617
623
|
username: url.username || undefined,
|
|
618
624
|
password: url.password || undefined,
|
|
619
625
|
ssl,
|
|
620
626
|
pool: {
|
|
621
|
-
max: searchParams.get('pool_max')
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
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
|
+
},
|
|
625
635
|
};
|
|
626
636
|
}
|
|
627
637
|
return {
|
|
@@ -632,14 +642,15 @@ export class NOORMME {
|
|
|
632
642
|
database: url.pathname.slice(1), // Remove leading slash
|
|
633
643
|
username: url.username || '',
|
|
634
644
|
password: url.password || '',
|
|
635
|
-
ssl: url.searchParams.get('ssl') === 'true' ||
|
|
636
|
-
|
|
645
|
+
ssl: url.searchParams.get('ssl') === 'true' ||
|
|
646
|
+
url.searchParams.get('sslmode') === 'require',
|
|
647
|
+
},
|
|
637
648
|
};
|
|
638
649
|
}
|
|
639
650
|
catch (error) {
|
|
640
651
|
throw new NoormError(`Failed to parse connection string: ${error instanceof Error ? error.message : String(error)}`, {
|
|
641
652
|
operation: 'connection_string_parsing',
|
|
642
|
-
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',
|
|
643
654
|
});
|
|
644
655
|
}
|
|
645
656
|
}
|
|
@@ -648,10 +659,14 @@ export class NOORMME {
|
|
|
648
659
|
*/
|
|
649
660
|
getDefaultPort(dialect) {
|
|
650
661
|
switch (dialect) {
|
|
651
|
-
case 'sqlite':
|
|
652
|
-
|
|
653
|
-
case '
|
|
654
|
-
|
|
662
|
+
case 'sqlite':
|
|
663
|
+
return 0;
|
|
664
|
+
case 'postgresql':
|
|
665
|
+
return 5432;
|
|
666
|
+
case 'mysql':
|
|
667
|
+
return 3306;
|
|
668
|
+
default:
|
|
669
|
+
return 0;
|
|
655
670
|
}
|
|
656
671
|
}
|
|
657
672
|
createDialect() {
|
|
@@ -659,7 +674,7 @@ export class NOORMME {
|
|
|
659
674
|
switch (dialect) {
|
|
660
675
|
case 'sqlite':
|
|
661
676
|
return new SqliteDialect({
|
|
662
|
-
database: new Database(connection.database)
|
|
677
|
+
database: new Database(connection.database),
|
|
663
678
|
});
|
|
664
679
|
case 'postgresql':
|
|
665
680
|
return new PostgresDialect({
|
|
@@ -673,7 +688,7 @@ export class NOORMME {
|
|
|
673
688
|
max: connection.pool?.max ?? 10,
|
|
674
689
|
min: connection.pool?.min ?? 0,
|
|
675
690
|
idleTimeoutMillis: connection.pool?.idleTimeoutMillis ?? 10000,
|
|
676
|
-
}
|
|
691
|
+
},
|
|
677
692
|
});
|
|
678
693
|
default:
|
|
679
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
|
/**
|