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
|
@@ -40,6 +40,7 @@ exports.generate = generate;
|
|
|
40
40
|
const fs_1 = require("fs");
|
|
41
41
|
const path = __importStar(require("path"));
|
|
42
42
|
const chalk_1 = __importDefault(require("chalk"));
|
|
43
|
+
const spinner_js_1 = require("../ui/spinner.js");
|
|
43
44
|
const noormme_js_1 = require("../../noormme.js");
|
|
44
45
|
const security_validator_js_1 = require("../../util/security-validator.js");
|
|
45
46
|
async function generate(options = {}) {
|
|
@@ -48,6 +49,8 @@ async function generate(options = {}) {
|
|
|
48
49
|
// SECURITY: Validate and sanitize database path to prevent path traversal attacks
|
|
49
50
|
const databasePathInput = options.database || process.env.DATABASE_PATH || './database.sqlite';
|
|
50
51
|
const databasePath = (0, security_validator_js_1.sanitizeDatabasePath)(databasePathInput);
|
|
52
|
+
const spinner = new spinner_js_1.AgenticSpinner();
|
|
53
|
+
spinner.start('Awakening connection to the Data Engine...');
|
|
51
54
|
const db = new noormme_js_1.NOORMME({
|
|
52
55
|
dialect: 'sqlite',
|
|
53
56
|
connection: {
|
|
@@ -55,17 +58,19 @@ async function generate(options = {}) {
|
|
|
55
58
|
host: 'localhost',
|
|
56
59
|
port: 0,
|
|
57
60
|
username: '',
|
|
58
|
-
password: ''
|
|
59
|
-
}
|
|
61
|
+
password: '',
|
|
62
|
+
},
|
|
60
63
|
});
|
|
61
64
|
await db.initialize();
|
|
65
|
+
spinner.start('Discovering cognitive schemas...');
|
|
62
66
|
const schemaInfo = await db.getSchemaInfo();
|
|
63
67
|
// SECURITY: Validate output directory to prevent path traversal attacks
|
|
64
68
|
const outputDir = options.output || './generated';
|
|
65
69
|
(0, security_validator_js_1.validateOutputDirectory)(outputDir);
|
|
66
70
|
const format = options.format || 'dts';
|
|
71
|
+
spinner.stop();
|
|
67
72
|
console.log(chalk_1.default.gray(`📁 Output directory: ${outputDir}`));
|
|
68
|
-
console.log(chalk_1.default.gray(`📊 Discovered ${schemaInfo.tables.length}
|
|
73
|
+
console.log(chalk_1.default.gray(`📊 Discovered ${schemaInfo.tables.length} tabular memories\n`));
|
|
69
74
|
// Ensure output directory exists
|
|
70
75
|
await fs_1.promises.mkdir(outputDir, { recursive: true });
|
|
71
76
|
let generatedFiles = [];
|
|
@@ -93,11 +98,12 @@ async function generate(options = {}) {
|
|
|
93
98
|
generatedFiles.push(configPath);
|
|
94
99
|
console.log(chalk_1.default.green(`✅ Generated automation config: automation.config.ts`));
|
|
95
100
|
// Generate usage examples
|
|
101
|
+
spinner.start('Pre-warming usage patterns...');
|
|
96
102
|
const examplesContent = generateUsageExamples(schemaInfo.tables);
|
|
97
103
|
const examplesPath = path.join(outputDir, 'usage-examples.ts');
|
|
98
104
|
await fs_1.promises.writeFile(examplesPath, examplesContent);
|
|
99
105
|
generatedFiles.push(examplesPath);
|
|
100
|
-
|
|
106
|
+
spinner.succeed(`Generated usage examples: usage-examples.ts`);
|
|
101
107
|
console.log(chalk_1.default.green.bold(`\n🎉 Generated ${generatedFiles.length} files successfully!`));
|
|
102
108
|
console.log(chalk_1.default.blue('\nNext steps:'));
|
|
103
109
|
console.log(chalk_1.default.gray('1. Import and use the generated types in your project'));
|
|
@@ -112,9 +118,11 @@ async function generate(options = {}) {
|
|
|
112
118
|
}
|
|
113
119
|
}
|
|
114
120
|
function generateTypeScriptTypes(tables) {
|
|
115
|
-
const interfaces = tables
|
|
121
|
+
const interfaces = tables
|
|
122
|
+
.map((table) => generateTableInterface(table))
|
|
123
|
+
.join('\n\n');
|
|
116
124
|
const databaseInterface = `export interface Database {
|
|
117
|
-
${tables.map(t => ` ${t.name}: ${pascalCase(t.name)}Table;`).join('\n')}
|
|
125
|
+
${tables.map((t) => ` ${t.name}: ${pascalCase(t.name)}Table;`).join('\n')}
|
|
118
126
|
}`;
|
|
119
127
|
return `// Auto-generated by NOORMME CLI
|
|
120
128
|
// Do not edit manually - regenerate with: npx noormme generate
|
|
@@ -124,14 +132,14 @@ ${interfaces}
|
|
|
124
132
|
${databaseInterface}
|
|
125
133
|
|
|
126
134
|
// Repository types for each table
|
|
127
|
-
${tables.map(table => generateRepositoryType(table)).join('\n\n')}
|
|
135
|
+
${tables.map((table) => generateRepositoryType(table)).join('\n\n')}
|
|
128
136
|
|
|
129
137
|
// Export all table types
|
|
130
138
|
export type {
|
|
131
|
-
${tables.map(t => ` ${pascalCase(t.name)}Table,`).join('\n')}
|
|
132
|
-
${tables.map(t => ` ${pascalCase(t.name)}Insert,`).join('\n')}
|
|
133
|
-
${tables.map(t => ` ${pascalCase(t.name)}Update,`).join('\n')}
|
|
134
|
-
${tables.map(t => ` ${pascalCase(t.name)}Repository,`).join('\n')}
|
|
139
|
+
${tables.map((t) => ` ${pascalCase(t.name)}Table,`).join('\n')}
|
|
140
|
+
${tables.map((t) => ` ${pascalCase(t.name)}Insert,`).join('\n')}
|
|
141
|
+
${tables.map((t) => ` ${pascalCase(t.name)}Update,`).join('\n')}
|
|
142
|
+
${tables.map((t) => ` ${pascalCase(t.name)}Repository,`).join('\n')}
|
|
135
143
|
}
|
|
136
144
|
`;
|
|
137
145
|
}
|
|
@@ -139,23 +147,21 @@ function generateTableInterface(table) {
|
|
|
139
147
|
const tableName = pascalCase(table.name);
|
|
140
148
|
// Base table interface
|
|
141
149
|
const baseInterface = `export interface ${tableName}Table {
|
|
142
|
-
${table.columns.map(col => generateColumnType(col)).join('\n')}
|
|
150
|
+
${table.columns.map((col) => generateColumnType(col)).join('\n')}
|
|
143
151
|
}`;
|
|
144
152
|
// Insert type (optional fields that have defaults or are auto-increment)
|
|
145
|
-
const requiredFields = table.columns.filter(col => !col.nullable &&
|
|
153
|
+
const requiredFields = table.columns.filter((col) => !col.nullable &&
|
|
146
154
|
!col.isAutoIncrement &&
|
|
147
155
|
col.defaultValue === undefined &&
|
|
148
156
|
!col.isPrimaryKey);
|
|
149
|
-
const optionalFields = table.columns.filter(col => col.nullable ||
|
|
150
|
-
col.isAutoIncrement ||
|
|
151
|
-
col.defaultValue !== undefined);
|
|
157
|
+
const optionalFields = table.columns.filter((col) => col.nullable || col.isAutoIncrement || col.defaultValue !== undefined);
|
|
152
158
|
const insertInterface = `export interface ${tableName}Insert {
|
|
153
|
-
${requiredFields.map(col => generateColumnType(col)).join('\n')}
|
|
154
|
-
${optionalFields.map(col => generateColumnType(col, true)).join('\n')}
|
|
159
|
+
${requiredFields.map((col) => generateColumnType(col)).join('\n')}
|
|
160
|
+
${optionalFields.map((col) => generateColumnType(col, true)).join('\n')}
|
|
155
161
|
}`;
|
|
156
162
|
// Update type (all fields optional except primary key)
|
|
157
163
|
const updateInterface = `export interface ${tableName}Update {
|
|
158
|
-
${table.columns.map(col => generateColumnType(col, !col.isPrimaryKey)).join('\n')}
|
|
164
|
+
${table.columns.map((col) => generateColumnType(col, !col.isPrimaryKey)).join('\n')}
|
|
159
165
|
}`;
|
|
160
166
|
return `${baseInterface}
|
|
161
167
|
|
|
@@ -195,8 +201,8 @@ function generateRepositoryType(table) {
|
|
|
195
201
|
}>;
|
|
196
202
|
withCount(id: ${primaryKeyType}, relationships: string[]): Promise<${tableName}Table & Record<string, number>>;
|
|
197
203
|
// Dynamic finders
|
|
198
|
-
${table.columns.map(col => ` findBy${pascalCase(col.name)}(value: ${mapColumnToTsType(col)}): Promise<${tableName}Table | null>;`).join('\n')}
|
|
199
|
-
${table.columns.map(col => ` findManyBy${pascalCase(col.name)}(value: ${mapColumnToTsType(col)}): Promise<${tableName}Table[]>;`).join('\n')}
|
|
204
|
+
${table.columns.map((col) => ` findBy${pascalCase(col.name)}(value: ${mapColumnToTsType(col)}): Promise<${tableName}Table | null>;`).join('\n')}
|
|
205
|
+
${table.columns.map((col) => ` findManyBy${pascalCase(col.name)}(value: ${mapColumnToTsType(col)}): Promise<${tableName}Table[]>;`).join('\n')}
|
|
200
206
|
}`;
|
|
201
207
|
}
|
|
202
208
|
function generateColumnType(column, optional = false) {
|
|
@@ -209,11 +215,16 @@ function generateColumnType(column, optional = false) {
|
|
|
209
215
|
function mapColumnToTsType(column) {
|
|
210
216
|
const type = column.type.toLowerCase();
|
|
211
217
|
// Integer types
|
|
212
|
-
if (type.includes('int') ||
|
|
218
|
+
if (type.includes('int') ||
|
|
219
|
+
type.includes('serial') ||
|
|
220
|
+
type.includes('bigint')) {
|
|
213
221
|
return 'number';
|
|
214
222
|
}
|
|
215
223
|
// Float types
|
|
216
|
-
if (type.includes('float') ||
|
|
224
|
+
if (type.includes('float') ||
|
|
225
|
+
type.includes('double') ||
|
|
226
|
+
type.includes('decimal') ||
|
|
227
|
+
type.includes('numeric')) {
|
|
217
228
|
return 'number';
|
|
218
229
|
}
|
|
219
230
|
// Boolean types
|
|
@@ -221,7 +232,9 @@ function mapColumnToTsType(column) {
|
|
|
221
232
|
return 'boolean';
|
|
222
233
|
}
|
|
223
234
|
// Date/time types
|
|
224
|
-
if (type.includes('date') ||
|
|
235
|
+
if (type.includes('date') ||
|
|
236
|
+
type.includes('time') ||
|
|
237
|
+
type.includes('timestamp')) {
|
|
225
238
|
return 'Date';
|
|
226
239
|
}
|
|
227
240
|
// JSON types
|
|
@@ -244,12 +257,12 @@ function getPrimaryKeyType(table) {
|
|
|
244
257
|
return 'unknown';
|
|
245
258
|
}
|
|
246
259
|
if (table.primaryKey.length === 1) {
|
|
247
|
-
const pkColumn = table.columns.find(col => col.name === table.primaryKey[0]);
|
|
260
|
+
const pkColumn = table.columns.find((col) => col.name === table.primaryKey[0]);
|
|
248
261
|
return pkColumn ? mapColumnToTsType(pkColumn) : 'unknown';
|
|
249
262
|
}
|
|
250
263
|
// Composite primary key
|
|
251
|
-
const types = table.primaryKey.map(pkCol => {
|
|
252
|
-
const column = table.columns.find(col => col.name === pkCol);
|
|
264
|
+
const types = table.primaryKey.map((pkCol) => {
|
|
265
|
+
const column = table.columns.find((col) => col.name === pkCol);
|
|
253
266
|
return column ? mapColumnToTsType(column) : 'any';
|
|
254
267
|
});
|
|
255
268
|
return `[${types.join(', ')}]`;
|
|
@@ -257,11 +270,12 @@ function getPrimaryKeyType(table) {
|
|
|
257
270
|
function generateRepositoryClasses(tables) {
|
|
258
271
|
const imports = `import { NOORMME } from 'noormme'
|
|
259
272
|
import type {
|
|
260
|
-
${tables.map(t => ` ${pascalCase(t.name)}Table,`).join('\n')}
|
|
261
|
-
${tables.map(t => ` ${pascalCase(t.name)}Insert,`).join('\n')}
|
|
262
|
-
${tables.map(t => ` ${pascalCase(t.name)}Update,`).join('\n')}
|
|
273
|
+
${tables.map((t) => ` ${pascalCase(t.name)}Table,`).join('\n')}
|
|
274
|
+
${tables.map((t) => ` ${pascalCase(t.name)}Insert,`).join('\n')}
|
|
275
|
+
${tables.map((t) => ` ${pascalCase(t.name)}Update,`).join('\n')}
|
|
263
276
|
} from './database'`;
|
|
264
|
-
const repositoryClasses = tables
|
|
277
|
+
const repositoryClasses = tables
|
|
278
|
+
.map((table) => {
|
|
265
279
|
const tableName = table.name;
|
|
266
280
|
const className = pascalCase(table.name) + 'Repository';
|
|
267
281
|
const primaryKeyType = getPrimaryKeyType(table);
|
|
@@ -304,23 +318,30 @@ ${tables.map(t => ` ${pascalCase(t.name)}Update,`).join('\n')}
|
|
|
304
318
|
}
|
|
305
319
|
|
|
306
320
|
// Dynamic finders
|
|
307
|
-
${table.columns
|
|
321
|
+
${table.columns
|
|
322
|
+
.map((col) => ` async findBy${pascalCase(col.name)}(value: ${mapColumnToTsType(col)}): Promise<${pascalCase(tableName)}Table | null> {
|
|
308
323
|
const repo = this.db.getRepository('${tableName}')
|
|
309
324
|
return await repo.findBy${pascalCase(col.name)}(value)
|
|
310
|
-
}`)
|
|
325
|
+
}`)
|
|
326
|
+
.join('\n')}
|
|
311
327
|
|
|
312
|
-
${table.columns
|
|
328
|
+
${table.columns
|
|
329
|
+
.map((col) => ` async findManyBy${pascalCase(col.name)}(value: ${mapColumnToTsType(col)}): Promise<${pascalCase(tableName)}Table[]> {
|
|
313
330
|
const repo = this.db.getRepository('${tableName}')
|
|
314
331
|
return await repo.findManyBy${pascalCase(col.name)}(value)
|
|
315
|
-
}`)
|
|
332
|
+
}`)
|
|
333
|
+
.join('\n')}
|
|
316
334
|
}`;
|
|
317
|
-
})
|
|
335
|
+
})
|
|
336
|
+
.join('\n\n');
|
|
318
337
|
const factoryClass = `export class RepositoryFactory {
|
|
319
338
|
constructor(private db: NOORMME) {}
|
|
320
339
|
|
|
321
|
-
${tables
|
|
340
|
+
${tables
|
|
341
|
+
.map((table) => ` get ${table.name}(): ${pascalCase(table.name)}Repository {
|
|
322
342
|
return new ${pascalCase(table.name)}Repository(this.db)
|
|
323
|
-
}`)
|
|
343
|
+
}`)
|
|
344
|
+
.join('\n')}
|
|
324
345
|
}`;
|
|
325
346
|
return `${imports}
|
|
326
347
|
|
|
@@ -389,14 +410,21 @@ export const automationConfig: Partial<NOORMConfig> = {
|
|
|
389
410
|
|
|
390
411
|
// Table-specific automation settings
|
|
391
412
|
export const tableAutomationSettings = {
|
|
392
|
-
${tables
|
|
413
|
+
${tables
|
|
414
|
+
.map((table) => ` ${table.name}: {
|
|
393
415
|
// Auto-generated settings for ${table.name} table
|
|
394
416
|
enableAutoIndexing: true,
|
|
395
417
|
enablePerformanceMonitoring: true,
|
|
396
418
|
recommendedIndexes: [
|
|
397
|
-
${table.columns
|
|
419
|
+
${table.columns
|
|
420
|
+
.filter((col) => col.name.includes('email') ||
|
|
421
|
+
col.name.includes('status') ||
|
|
422
|
+
col.name.includes('created'))
|
|
423
|
+
.map((col) => `'${col.name}'`)
|
|
424
|
+
.join(',\n ') || '// No recommended indexes'}
|
|
398
425
|
]
|
|
399
|
-
},`)
|
|
426
|
+
},`)
|
|
427
|
+
.join('\n')}
|
|
400
428
|
}
|
|
401
429
|
|
|
402
430
|
// Usage example:
|
|
@@ -431,7 +459,11 @@ async function basicCrudExample() {
|
|
|
431
459
|
|
|
432
460
|
// Create a new record
|
|
433
461
|
const new${pascalCase(tableName)} = await ${tableName}Repo.create({
|
|
434
|
-
${firstTable?.columns
|
|
462
|
+
${firstTable?.columns
|
|
463
|
+
.filter((col) => !col.isAutoIncrement && !col.isPrimaryKey)
|
|
464
|
+
.slice(0, 3)
|
|
465
|
+
.map((col) => `${col.name}: 'example_value'`)
|
|
466
|
+
.join(',\n ') || '// Add your data here'}
|
|
435
467
|
})
|
|
436
468
|
|
|
437
469
|
// Find by ID
|
|
@@ -450,12 +482,17 @@ async function basicCrudExample() {
|
|
|
450
482
|
async function dynamicFinderExample() {
|
|
451
483
|
const ${tableName}Repo = repositories.${tableName}
|
|
452
484
|
|
|
453
|
-
${firstTable?.columns
|
|
485
|
+
${firstTable?.columns
|
|
486
|
+
.filter((col) => !col.isPrimaryKey)
|
|
487
|
+
.slice(0, 2)
|
|
488
|
+
.map((col) => `
|
|
454
489
|
// Find by ${col.name}
|
|
455
490
|
const ${tableName}By${pascalCase(col.name)} = await ${tableName}Repo.findBy${pascalCase(col.name)}('value')
|
|
456
491
|
|
|
457
492
|
// Find many by ${col.name}
|
|
458
|
-
const ${tableName}sBy${pascalCase(col.name)} = await ${tableName}Repo.findManyBy${pascalCase(col.name)}('value')`)
|
|
493
|
+
const ${tableName}sBy${pascalCase(col.name)} = await ${tableName}Repo.findManyBy${pascalCase(col.name)}('value')`)
|
|
494
|
+
.join('') ||
|
|
495
|
+
'// Dynamic finders will be available based on your table columns'}
|
|
459
496
|
}
|
|
460
497
|
|
|
461
498
|
// Example 3: Direct repository access
|
|
@@ -41,6 +41,7 @@ const inquirer_1 = __importDefault(require("inquirer"));
|
|
|
41
41
|
const fs_1 = require("fs");
|
|
42
42
|
const path = __importStar(require("path"));
|
|
43
43
|
const chalk_1 = __importDefault(require("chalk"));
|
|
44
|
+
const spinner_js_1 = require("../ui/spinner.js");
|
|
44
45
|
const security_validator_js_1 = require("../../util/security-validator.js");
|
|
45
46
|
async function init(options) {
|
|
46
47
|
console.log(chalk_1.default.blue.bold('\n🎯 NOORMME Zero-Configuration Setup\n'));
|
|
@@ -52,11 +53,12 @@ async function init(options) {
|
|
|
52
53
|
// SECURITY: Validate output directory to prevent path traversal attacks
|
|
53
54
|
const outputDir = options.output || 'lib';
|
|
54
55
|
(0, security_validator_js_1.validateOutputDirectory)(outputDir);
|
|
55
|
-
|
|
56
|
+
const spinner = new spinner_js_1.AgenticSpinner();
|
|
57
|
+
spinner.start('Detecting existing Data Engine matrix...');
|
|
56
58
|
// Check if database exists
|
|
57
59
|
const dbExists = await checkDatabaseExists(databasePath);
|
|
58
60
|
if (dbExists) {
|
|
59
|
-
|
|
61
|
+
spinner.succeed(`Found existing data layer: ${databasePath}`);
|
|
60
62
|
console.log(chalk_1.default.gray('NOORMME will automatically discover your schema and optimize performance\n'));
|
|
61
63
|
}
|
|
62
64
|
else {
|
|
@@ -98,11 +100,13 @@ async function init(options) {
|
|
|
98
100
|
return;
|
|
99
101
|
}
|
|
100
102
|
// Generate files with automation focus
|
|
103
|
+
spinner.start('Bootstrapping sovereign infrastructure...');
|
|
101
104
|
await generateDbFile(databasePath, outputDir, options.force, autoOptimize, autoIndex);
|
|
102
105
|
await generateEnvExample(databasePath);
|
|
103
106
|
await generateAutomationConfig(databasePath, autoOptimize, autoIndex);
|
|
104
107
|
await generateReadme();
|
|
105
108
|
await generatePackageScripts();
|
|
109
|
+
spinner.succeed('Infrastructure sequence complete');
|
|
106
110
|
console.log(chalk_1.default.green.bold('\n✅ NOORMME initialized with complete automation!\n'));
|
|
107
111
|
console.log(chalk_1.default.blue('🚀 What NOORMME will do automatically:'));
|
|
108
112
|
console.log(chalk_1.default.gray('✅ Discover your existing database schema'));
|
|
@@ -490,7 +494,7 @@ async function generatePackageScripts() {
|
|
|
490
494
|
'db:analyze': 'noormme analyze --report',
|
|
491
495
|
'db:migrate': 'noormme migrate --latest',
|
|
492
496
|
'db:watch': 'noormme watch --auto-optimize',
|
|
493
|
-
'db:status': 'noormme status'
|
|
497
|
+
'db:status': 'noormme status',
|
|
494
498
|
};
|
|
495
499
|
let hasChanges = false;
|
|
496
500
|
for (const [key, value] of Object.entries(noormmeScripts)) {
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.inspect = inspect;
|
|
7
7
|
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const spinner_js_1 = require("../ui/spinner.js");
|
|
8
9
|
const noormme_js_1 = require("../../noormme.js");
|
|
9
10
|
const security_validator_js_1 = require("../../util/security-validator.js");
|
|
10
11
|
async function inspect(tableName, options = {}) {
|
|
@@ -13,6 +14,8 @@ async function inspect(tableName, options = {}) {
|
|
|
13
14
|
// SECURITY: Validate and sanitize database path to prevent path traversal attacks
|
|
14
15
|
const databasePathInput = options.database || process.env.DATABASE_PATH || './database.sqlite';
|
|
15
16
|
const databasePath = (0, security_validator_js_1.sanitizeDatabasePath)(databasePathInput);
|
|
17
|
+
const spinner = new spinner_js_1.AgenticSpinner();
|
|
18
|
+
spinner.start('Connecting to Data Engine layer...');
|
|
16
19
|
const db = new noormme_js_1.NOORMME({
|
|
17
20
|
dialect: 'sqlite',
|
|
18
21
|
connection: {
|
|
@@ -20,21 +23,23 @@ async function inspect(tableName, options = {}) {
|
|
|
20
23
|
host: 'localhost',
|
|
21
24
|
port: 0,
|
|
22
25
|
username: '',
|
|
23
|
-
password: ''
|
|
24
|
-
}
|
|
26
|
+
password: '',
|
|
27
|
+
},
|
|
25
28
|
});
|
|
26
29
|
await db.initialize();
|
|
27
30
|
console.log(chalk_1.default.gray(`📁 Database: ${databasePath}\n`));
|
|
31
|
+
spinner.start('Introspecting cognitive matrix...');
|
|
28
32
|
const schemaInfo = await db.getSchemaInfo();
|
|
33
|
+
spinner.stop();
|
|
29
34
|
if (tableName) {
|
|
30
35
|
// SECURITY: Validate table name to prevent SQL injection
|
|
31
36
|
(0, security_validator_js_1.validateIdentifier)(tableName, 'table name');
|
|
32
37
|
// Show specific table with automation insights
|
|
33
|
-
const table = schemaInfo.tables.find(t => t.name === tableName);
|
|
38
|
+
const table = schemaInfo.tables.find((t) => t.name === tableName);
|
|
34
39
|
if (!table) {
|
|
35
40
|
console.error(chalk_1.default.red(`❌ Table '${tableName}' not found`));
|
|
36
41
|
console.log(chalk_1.default.gray('Available tables:'));
|
|
37
|
-
schemaInfo.tables.forEach(t => console.log(chalk_1.default.gray(` - ${t.name}`)));
|
|
42
|
+
schemaInfo.tables.forEach((t) => console.log(chalk_1.default.gray(` - ${t.name}`)));
|
|
38
43
|
process.exit(1);
|
|
39
44
|
}
|
|
40
45
|
const rowCount = await getTableRowCount(db, tableName);
|
|
@@ -87,7 +92,9 @@ async function inspect(tableName, options = {}) {
|
|
|
87
92
|
}
|
|
88
93
|
async function getTableRowCount(db, tableName) {
|
|
89
94
|
try {
|
|
90
|
-
const introspector = db.getKysely()
|
|
95
|
+
const introspector = db.getKysely()
|
|
96
|
+
.getExecutor()
|
|
97
|
+
.adapter.createIntrospector(db.getKysely());
|
|
91
98
|
return await introspector.getRowCount(tableName);
|
|
92
99
|
}
|
|
93
100
|
catch {
|
|
@@ -95,28 +102,82 @@ async function getTableRowCount(db, tableName) {
|
|
|
95
102
|
}
|
|
96
103
|
}
|
|
97
104
|
function showTablesList(tables, rowCounts) {
|
|
98
|
-
const tableData = tables.map(table => ({
|
|
105
|
+
const tableData = tables.map((table) => ({
|
|
99
106
|
name: table.name,
|
|
100
107
|
rows: rowCounts.get(table.name) ?? 0,
|
|
101
108
|
columns: table.columns.length,
|
|
102
109
|
primaryKey: table.primaryKey?.join(', ') || 'None',
|
|
103
110
|
foreignKeys: table.foreignKeys.length,
|
|
104
|
-
indexes: table.indexes.length
|
|
111
|
+
indexes: table.indexes.length,
|
|
105
112
|
}));
|
|
106
113
|
// Simple table formatting
|
|
107
|
-
console.log(chalk_1.default.gray('┌─' +
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
console.log(chalk_1.default.gray('┌─' +
|
|
115
|
+
'─'.repeat(20) +
|
|
116
|
+
'┬─' +
|
|
117
|
+
'─'.repeat(10) +
|
|
118
|
+
'┬─' +
|
|
119
|
+
'─'.repeat(8) +
|
|
120
|
+
'┬─' +
|
|
121
|
+
'─'.repeat(15) +
|
|
122
|
+
'┬─' +
|
|
123
|
+
'─'.repeat(5) +
|
|
124
|
+
'┬─' +
|
|
125
|
+
'─'.repeat(8) +
|
|
126
|
+
'┐'));
|
|
127
|
+
console.log(chalk_1.default.gray('│ ') +
|
|
128
|
+
chalk_1.default.bold('Table Name'.padEnd(19)) +
|
|
129
|
+
chalk_1.default.gray('│ ') +
|
|
130
|
+
chalk_1.default.bold('Rows'.padEnd(9)) +
|
|
131
|
+
chalk_1.default.gray('│ ') +
|
|
132
|
+
chalk_1.default.bold('Cols'.padEnd(7)) +
|
|
133
|
+
chalk_1.default.gray('│ ') +
|
|
134
|
+
chalk_1.default.bold('Primary Key'.padEnd(14)) +
|
|
135
|
+
chalk_1.default.gray('│ ') +
|
|
136
|
+
chalk_1.default.bold('FKs'.padEnd(4)) +
|
|
137
|
+
chalk_1.default.gray('│ ') +
|
|
138
|
+
chalk_1.default.bold('Indexes'.padEnd(7)) +
|
|
139
|
+
chalk_1.default.gray('│'));
|
|
140
|
+
console.log(chalk_1.default.gray('├─' +
|
|
141
|
+
'─'.repeat(20) +
|
|
142
|
+
'┼─' +
|
|
143
|
+
'─'.repeat(10) +
|
|
144
|
+
'┼─' +
|
|
145
|
+
'─'.repeat(8) +
|
|
146
|
+
'┼─' +
|
|
147
|
+
'─'.repeat(15) +
|
|
148
|
+
'┼─' +
|
|
149
|
+
'─'.repeat(5) +
|
|
150
|
+
'┼─' +
|
|
151
|
+
'─'.repeat(8) +
|
|
152
|
+
'┤'));
|
|
153
|
+
tableData.forEach((table) => {
|
|
154
|
+
console.log(chalk_1.default.gray('│ ') +
|
|
155
|
+
chalk_1.default.cyan(table.name.padEnd(19)) +
|
|
156
|
+
chalk_1.default.gray('│ ') +
|
|
157
|
+
String(table.rows.toLocaleString()).padEnd(9) +
|
|
158
|
+
chalk_1.default.gray('│ ') +
|
|
159
|
+
String(table.columns).padEnd(7) +
|
|
160
|
+
chalk_1.default.gray('│ ') +
|
|
161
|
+
table.primaryKey.padEnd(14) +
|
|
162
|
+
chalk_1.default.gray('│ ') +
|
|
163
|
+
String(table.foreignKeys).padEnd(4) +
|
|
164
|
+
chalk_1.default.gray('│ ') +
|
|
165
|
+
String(table.indexes).padEnd(7) +
|
|
117
166
|
chalk_1.default.gray('│'));
|
|
118
167
|
});
|
|
119
|
-
console.log(chalk_1.default.gray('└─' +
|
|
168
|
+
console.log(chalk_1.default.gray('└─' +
|
|
169
|
+
'─'.repeat(20) +
|
|
170
|
+
'┴─' +
|
|
171
|
+
'─'.repeat(10) +
|
|
172
|
+
'┴─' +
|
|
173
|
+
'─'.repeat(8) +
|
|
174
|
+
'┴─' +
|
|
175
|
+
'─'.repeat(15) +
|
|
176
|
+
'┴─' +
|
|
177
|
+
'─'.repeat(5) +
|
|
178
|
+
'┴─' +
|
|
179
|
+
'─'.repeat(8) +
|
|
180
|
+
'┘'));
|
|
120
181
|
}
|
|
121
182
|
async function showTableOptimizations(table, db) {
|
|
122
183
|
try {
|
|
@@ -134,7 +195,8 @@ async function showTableOptimizations(table, db) {
|
|
|
134
195
|
console.log(chalk_1.default.green('✅ No optimization recommendations for this table'));
|
|
135
196
|
}
|
|
136
197
|
// Check for foreign key constraints
|
|
137
|
-
if (table.foreignKeys.length === 0 &&
|
|
198
|
+
if (table.foreignKeys.length === 0 &&
|
|
199
|
+
table.columns.some((col) => col.name.includes('_id'))) {
|
|
138
200
|
console.log(chalk_1.default.yellow('💡 Consider adding foreign key constraints for data integrity'));
|
|
139
201
|
}
|
|
140
202
|
}
|
|
@@ -222,7 +284,9 @@ async function showIndexAnalysis(db) {
|
|
|
222
284
|
const indexRecs = await db.getSQLiteIndexRecommendations();
|
|
223
285
|
if (indexRecs.recommendations.length > 0) {
|
|
224
286
|
console.log(chalk_1.default.yellow(`💡 ${indexRecs.recommendations.length} index recommendations available:`));
|
|
225
|
-
indexRecs.recommendations
|
|
287
|
+
indexRecs.recommendations
|
|
288
|
+
.slice(0, 10)
|
|
289
|
+
.forEach((rec, index) => {
|
|
226
290
|
console.log(chalk_1.default.gray(` ${index + 1}. ${rec.table}.${rec.column} - ${rec.reason}`));
|
|
227
291
|
});
|
|
228
292
|
if (indexRecs.recommendations.length > 10) {
|
|
@@ -260,7 +324,8 @@ async function showAutomationRecommendations(schemaInfo, db) {
|
|
|
260
324
|
recommendations.push(`Consider adding indexes to tables: ${tablesWithoutIndexes.map((t) => t.name).join(', ')}`);
|
|
261
325
|
}
|
|
262
326
|
// Check for missing foreign keys
|
|
263
|
-
const tablesWithIdColumns = schemaInfo.tables.filter((table) => table.columns.some((col) => col.name.includes('_id')) &&
|
|
327
|
+
const tablesWithIdColumns = schemaInfo.tables.filter((table) => table.columns.some((col) => col.name.includes('_id')) &&
|
|
328
|
+
table.foreignKeys.length === 0);
|
|
264
329
|
if (tablesWithIdColumns.length > 0) {
|
|
265
330
|
recommendations.push(`Add foreign key constraints to tables: ${tablesWithIdColumns.map((t) => t.name).join(', ')}`);
|
|
266
331
|
}
|
|
@@ -306,20 +371,56 @@ function showTableDetails(table, relationships, db, rowCount = 0) {
|
|
|
306
371
|
console.log();
|
|
307
372
|
// Columns
|
|
308
373
|
console.log(chalk_1.default.blue.bold('Columns:'));
|
|
309
|
-
console.log(chalk_1.default.gray('┌─' +
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
374
|
+
console.log(chalk_1.default.gray('┌─' +
|
|
375
|
+
'─'.repeat(25) +
|
|
376
|
+
'┬─' +
|
|
377
|
+
'─'.repeat(15) +
|
|
378
|
+
'┬─' +
|
|
379
|
+
'─'.repeat(8) +
|
|
380
|
+
'┬─' +
|
|
381
|
+
'─'.repeat(10) +
|
|
382
|
+
'┐'));
|
|
383
|
+
console.log(chalk_1.default.gray('│ ') +
|
|
384
|
+
chalk_1.default.bold('Name'.padEnd(24)) +
|
|
385
|
+
chalk_1.default.gray('│ ') +
|
|
386
|
+
chalk_1.default.bold('Type'.padEnd(14)) +
|
|
387
|
+
chalk_1.default.gray('│ ') +
|
|
388
|
+
chalk_1.default.bold('Nullable'.padEnd(7)) +
|
|
389
|
+
chalk_1.default.gray('│ ') +
|
|
390
|
+
chalk_1.default.bold('Default'.padEnd(9)) +
|
|
391
|
+
chalk_1.default.gray('│'));
|
|
392
|
+
console.log(chalk_1.default.gray('├─' +
|
|
393
|
+
'─'.repeat(25) +
|
|
394
|
+
'┼─' +
|
|
395
|
+
'─'.repeat(15) +
|
|
396
|
+
'┼─' +
|
|
397
|
+
'─'.repeat(8) +
|
|
398
|
+
'┼─' +
|
|
399
|
+
'─'.repeat(10) +
|
|
400
|
+
'┤'));
|
|
401
|
+
table.columns.forEach((col) => {
|
|
313
402
|
const name = col.isPrimaryKey ? chalk_1.default.yellow(`${col.name} (PK)`) : col.name;
|
|
314
403
|
const nullable = col.nullable ? chalk_1.default.green('YES') : chalk_1.default.red('NO');
|
|
315
404
|
const defaultValue = col.defaultValue ? String(col.defaultValue) : '';
|
|
316
|
-
console.log(chalk_1.default.gray('│ ') +
|
|
317
|
-
|
|
318
|
-
chalk_1.default.gray('│ ') +
|
|
319
|
-
|
|
405
|
+
console.log(chalk_1.default.gray('│ ') +
|
|
406
|
+
name.padEnd(24) +
|
|
407
|
+
chalk_1.default.gray('│ ') +
|
|
408
|
+
col.type.padEnd(14) +
|
|
409
|
+
chalk_1.default.gray('│ ') +
|
|
410
|
+
nullable.padEnd(7) +
|
|
411
|
+
chalk_1.default.gray('│ ') +
|
|
412
|
+
defaultValue.padEnd(9) +
|
|
320
413
|
chalk_1.default.gray('│'));
|
|
321
414
|
});
|
|
322
|
-
console.log(chalk_1.default.gray('└─' +
|
|
415
|
+
console.log(chalk_1.default.gray('└─' +
|
|
416
|
+
'─'.repeat(25) +
|
|
417
|
+
'┴─' +
|
|
418
|
+
'─'.repeat(15) +
|
|
419
|
+
'┴─' +
|
|
420
|
+
'─'.repeat(8) +
|
|
421
|
+
'┴─' +
|
|
422
|
+
'─'.repeat(10) +
|
|
423
|
+
'┘'));
|
|
323
424
|
// Primary Key
|
|
324
425
|
if (table.primaryKey && table.primaryKey.length > 0) {
|
|
325
426
|
console.log();
|
|
@@ -330,7 +431,7 @@ function showTableDetails(table, relationships, db, rowCount = 0) {
|
|
|
330
431
|
if (table.foreignKeys.length > 0) {
|
|
331
432
|
console.log();
|
|
332
433
|
console.log(chalk_1.default.blue.bold('Foreign Keys:'));
|
|
333
|
-
table.foreignKeys.forEach(fk => {
|
|
434
|
+
table.foreignKeys.forEach((fk) => {
|
|
334
435
|
console.log(chalk_1.default.gray(` ${fk.column} → ${fk.referencedTable}.${fk.referencedColumn}`));
|
|
335
436
|
if (fk.onDelete)
|
|
336
437
|
console.log(chalk_1.default.gray(` ON DELETE ${fk.onDelete}`));
|
|
@@ -342,17 +443,17 @@ function showTableDetails(table, relationships, db, rowCount = 0) {
|
|
|
342
443
|
if (table.indexes.length > 0) {
|
|
343
444
|
console.log();
|
|
344
445
|
console.log(chalk_1.default.blue.bold('Indexes:'));
|
|
345
|
-
table.indexes.forEach(idx => {
|
|
446
|
+
table.indexes.forEach((idx) => {
|
|
346
447
|
const type = idx.unique ? chalk_1.default.yellow('UNIQUE') : 'INDEX';
|
|
347
448
|
console.log(chalk_1.default.gray(` ${idx.name} (${type}): ${idx.columns.join(', ')}`));
|
|
348
449
|
});
|
|
349
450
|
}
|
|
350
451
|
// Relationships for this table
|
|
351
|
-
const tableRelationships = relationships.filter(r => r.fromTable === table.name || r.toTable === table.name);
|
|
452
|
+
const tableRelationships = relationships.filter((r) => r.fromTable === table.name || r.toTable === table.name);
|
|
352
453
|
if (tableRelationships.length > 0) {
|
|
353
454
|
console.log();
|
|
354
455
|
console.log(chalk_1.default.blue.bold('Relationships:'));
|
|
355
|
-
tableRelationships.forEach(rel => {
|
|
456
|
+
tableRelationships.forEach((rel) => {
|
|
356
457
|
const direction = rel.fromTable === table.name ? '→' : '←';
|
|
357
458
|
const otherTable = rel.fromTable === table.name ? rel.toTable : rel.fromTable;
|
|
358
459
|
const type = rel.type.toUpperCase().replace('-', ' ');
|
|
@@ -367,7 +468,9 @@ function showTableDetails(table, relationships, db, rowCount = 0) {
|
|
|
367
468
|
console.log(chalk_1.default.gray(`const records = await ${table.name}Repo.findAll()`));
|
|
368
469
|
console.log(chalk_1.default.gray(`const record = await ${table.name}Repo.findById(1)`));
|
|
369
470
|
if (tableRelationships.length > 0) {
|
|
370
|
-
const relationshipNames = tableRelationships
|
|
471
|
+
const relationshipNames = tableRelationships
|
|
472
|
+
.map((r) => `'${r.name}'`)
|
|
473
|
+
.join(', ');
|
|
371
474
|
console.log(chalk_1.default.gray(`const withRelations = await ${table.name}Repo.findWithRelations(1, [${relationshipNames}])`));
|
|
372
475
|
}
|
|
373
476
|
console.log(chalk_1.default.gray('```'));
|
|
@@ -377,7 +480,7 @@ function showRelationships(relationships) {
|
|
|
377
480
|
console.log(chalk_1.default.gray('No relationships found.'));
|
|
378
481
|
return;
|
|
379
482
|
}
|
|
380
|
-
relationships.forEach(rel => {
|
|
483
|
+
relationships.forEach((rel) => {
|
|
381
484
|
const type = rel.type.toUpperCase().replace('-', ' ');
|
|
382
485
|
console.log(chalk_1.default.cyan(`${rel.name} (${type})`));
|
|
383
486
|
console.log(chalk_1.default.gray(` ${rel.fromTable}.${rel.fromColumn} → ${rel.toTable}.${rel.toColumn}`));
|
|
@@ -19,8 +19,8 @@ async function migrate(options) {
|
|
|
19
19
|
host: 'localhost',
|
|
20
20
|
port: 0,
|
|
21
21
|
username: '',
|
|
22
|
-
password: ''
|
|
23
|
-
}
|
|
22
|
+
password: '',
|
|
23
|
+
},
|
|
24
24
|
});
|
|
25
25
|
await db.initialize();
|
|
26
26
|
const migrationManager = sqlite_migration_manager_js_1.SQLiteMigrationManager.getInstance(db.getKysely());
|
|
@@ -49,7 +49,8 @@ async function migrate(options) {
|
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
51
|
// Show migration status
|
|
52
|
-
if (options.status ||
|
|
52
|
+
if (options.status ||
|
|
53
|
+
(!options.to && !options.latest && !options.rollback)) {
|
|
53
54
|
console.log(chalk_1.default.blue('📊 Migration Status:'));
|
|
54
55
|
try {
|
|
55
56
|
const status = await migrationManager.getStatus();
|
|
@@ -95,7 +96,7 @@ async function migrate(options) {
|
|
|
95
96
|
else {
|
|
96
97
|
console.log(chalk_1.default.gray('No migrations to apply or migration failed.'));
|
|
97
98
|
if (result.warnings.length > 0) {
|
|
98
|
-
result.warnings.forEach(w => console.warn(chalk_1.default.yellow(`⚠️ ${w}`)));
|
|
99
|
+
result.warnings.forEach((w) => console.warn(chalk_1.default.yellow(`⚠️ ${w}`)));
|
|
99
100
|
}
|
|
100
101
|
}
|
|
101
102
|
}
|