noormme 1.0.0 → 1.0.2
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/LICENSE +89 -21
- package/README.md +195 -578
- package/dist/cjs/cli/commands/analyze.js +4 -1
- package/dist/cjs/cli/commands/generate.js +48 -8
- package/dist/cjs/cli/commands/init.js +54 -14
- package/dist/cjs/cli/commands/inspect.js +10 -3
- package/dist/cjs/cli/commands/migrate.js +38 -2
- package/dist/cjs/cli/commands/optimize.js +4 -1
- package/dist/cjs/cli/commands/status.js +41 -5
- package/dist/cjs/cli/commands/watch.js +4 -1
- package/dist/cjs/cli/index.js +4 -1
- package/dist/cjs/dialect/database-introspector.js +16 -21
- package/dist/cjs/dialect/sqlite/sqlite-introspector.js +13 -24
- package/dist/cjs/dynamic/dynamic.d.ts +20 -0
- package/dist/cjs/dynamic/dynamic.js +25 -0
- package/dist/cjs/edge-runtime/edge-config.d.ts +125 -0
- package/dist/cjs/edge-runtime/edge-config.js +323 -0
- package/dist/cjs/errors/NoormError.d.ts +27 -4
- package/dist/cjs/errors/NoormError.js +142 -21
- package/dist/cjs/logging/logger.d.ts +7 -2
- package/dist/cjs/logging/logger.js +21 -7
- package/dist/cjs/noormme.d.ts +12 -8
- package/dist/cjs/noormme.js +133 -61
- package/dist/cjs/operation-node/column-node.js +4 -0
- package/dist/cjs/operation-node/identifier-node.js +4 -0
- package/dist/cjs/operation-node/table-node.js +7 -0
- package/dist/cjs/parser/reference-parser.js +5 -0
- package/dist/cjs/parser/table-parser.js +2 -0
- package/dist/cjs/performance/index.d.ts +44 -0
- package/dist/cjs/performance/index.js +64 -0
- package/dist/cjs/performance/query-optimizer.d.ts +134 -0
- package/dist/cjs/performance/query-optimizer.js +391 -0
- package/dist/cjs/performance/services/cache-service.d.ts +177 -0
- package/dist/cjs/performance/services/cache-service.js +415 -0
- package/dist/cjs/performance/services/connection-factory.d.ts +198 -0
- package/dist/cjs/performance/services/connection-factory.js +498 -0
- package/dist/cjs/performance/services/metrics-collector.d.ts +162 -0
- package/dist/cjs/performance/services/metrics-collector.js +406 -0
- package/dist/cjs/performance/utils/query-parser.d.ts +123 -0
- package/dist/cjs/performance/utils/query-parser.js +295 -0
- package/dist/cjs/raw-builder/sql.d.ts +73 -26
- package/dist/cjs/raw-builder/sql.js +9 -0
- package/dist/cjs/repository/repository-factory.d.ts +10 -42
- package/dist/cjs/repository/repository-factory.js +276 -394
- package/dist/cjs/schema/core/coordinators/schema-discovery.coordinator.js +6 -4
- package/dist/cjs/schema/core/factories/discovery-factory.js +5 -5
- package/dist/cjs/schema/core/utils/name-generator.js +34 -2
- package/dist/cjs/schema/core/utils/type-mapper.d.ts +19 -14
- package/dist/cjs/schema/core/utils/type-mapper.js +4 -7
- package/dist/cjs/schema/dialects/sqlite/discovery/sqlite-constraint-discovery.js +3 -2
- package/dist/cjs/schema/dialects/sqlite/sqlite-discovery.coordinator.d.ts +2 -0
- package/dist/cjs/schema/dialects/sqlite/sqlite-discovery.coordinator.js +19 -5
- package/dist/cjs/schema/test/dialect-capabilities.test.js +6 -0
- package/dist/cjs/schema/test/error-handling.test.js +52 -33
- package/dist/cjs/schema/test/integration.test.js +51 -5
- package/dist/cjs/schema/test/sqlite-discovery-coordinator.test.js +8 -4
- package/dist/cjs/sqlite-migration/index.js +35 -2
- package/dist/cjs/testing/test-utils.d.ts +5 -0
- package/dist/cjs/testing/test-utils.js +66 -6
- package/dist/cjs/types/index.d.ts +78 -13
- package/dist/cjs/types/index.js +23 -0
- package/dist/cjs/types/type-generator.d.ts +8 -0
- package/dist/cjs/types/type-generator.js +86 -17
- package/dist/cjs/util/safe-sql-helpers.d.ts +124 -0
- package/dist/cjs/util/safe-sql-helpers.js +221 -0
- package/dist/cjs/util/security-validator.d.ts +44 -0
- package/dist/cjs/util/security-validator.js +256 -0
- package/dist/cjs/util/security.d.ts +60 -0
- package/dist/cjs/util/security.js +137 -0
- package/dist/cjs/watch/schema-watcher.js +26 -7
- package/dist/esm/cli/commands/generate.js +10 -6
- package/dist/esm/cli/commands/init.js +15 -11
- package/dist/esm/cli/commands/inspect.js +6 -2
- package/dist/esm/cli/commands/status.js +3 -3
- package/dist/esm/dialect/database-introspector.js +16 -21
- package/dist/esm/dialect/sqlite/sqlite-introspector.js +13 -24
- package/dist/esm/dynamic/dynamic.d.ts +20 -0
- package/dist/esm/dynamic/dynamic.js +25 -0
- package/dist/esm/edge-runtime/edge-config.d.ts +125 -0
- package/dist/esm/edge-runtime/edge-config.js +281 -0
- package/dist/esm/errors/NoormError.d.ts +27 -4
- package/dist/esm/errors/NoormError.js +134 -18
- package/dist/esm/logging/logger.d.ts +7 -2
- package/dist/esm/logging/logger.js +21 -7
- package/dist/esm/noormme.d.ts +12 -8
- package/dist/esm/noormme.js +130 -61
- package/dist/esm/operation-node/column-node.js +4 -0
- package/dist/esm/operation-node/identifier-node.js +4 -0
- package/dist/esm/operation-node/table-node.js +7 -0
- package/dist/esm/parser/reference-parser.js +5 -0
- package/dist/esm/parser/table-parser.js +2 -0
- package/dist/esm/performance/index.d.ts +44 -0
- package/dist/esm/performance/index.js +48 -0
- package/dist/esm/performance/query-optimizer.d.ts +134 -0
- package/dist/esm/performance/query-optimizer.js +387 -0
- package/dist/esm/performance/services/cache-service.d.ts +177 -0
- package/dist/esm/performance/services/cache-service.js +410 -0
- package/dist/esm/performance/services/connection-factory.d.ts +198 -0
- package/dist/esm/performance/services/connection-factory.js +493 -0
- package/dist/esm/performance/services/metrics-collector.d.ts +162 -0
- package/dist/esm/performance/services/metrics-collector.js +402 -0
- package/dist/esm/performance/utils/query-parser.d.ts +123 -0
- package/dist/esm/performance/utils/query-parser.js +292 -0
- package/dist/esm/raw-builder/sql.d.ts +73 -26
- package/dist/esm/raw-builder/sql.js +9 -0
- package/dist/esm/repository/repository-factory.d.ts +10 -42
- package/dist/esm/repository/repository-factory.js +277 -395
- package/dist/esm/schema/core/coordinators/schema-discovery.coordinator.js +6 -4
- package/dist/esm/schema/core/factories/discovery-factory.js +5 -5
- package/dist/esm/schema/core/utils/name-generator.js +34 -2
- package/dist/esm/schema/core/utils/type-mapper.d.ts +19 -14
- package/dist/esm/schema/core/utils/type-mapper.js +4 -7
- package/dist/esm/schema/dialects/sqlite/discovery/sqlite-constraint-discovery.js +3 -2
- package/dist/esm/schema/dialects/sqlite/sqlite-discovery.coordinator.d.ts +2 -0
- package/dist/esm/schema/dialects/sqlite/sqlite-discovery.coordinator.js +19 -5
- package/dist/esm/schema/test/dialect-capabilities.test.js +6 -0
- package/dist/esm/schema/test/error-handling.test.js +52 -33
- package/dist/esm/schema/test/integration.test.js +18 -5
- package/dist/esm/schema/test/sqlite-discovery-coordinator.test.js +8 -4
- package/dist/esm/testing/test-utils.d.ts +5 -0
- package/dist/esm/testing/test-utils.js +66 -6
- package/dist/esm/types/index.d.ts +78 -13
- package/dist/esm/types/index.js +22 -1
- package/dist/esm/types/type-generator.d.ts +8 -0
- package/dist/esm/types/type-generator.js +86 -17
- package/dist/esm/util/safe-sql-helpers.d.ts +124 -0
- package/dist/esm/util/safe-sql-helpers.js +209 -0
- package/dist/esm/util/security-validator.d.ts +44 -0
- package/dist/esm/util/security-validator.js +246 -0
- package/dist/esm/util/security.d.ts +60 -0
- package/dist/esm/util/security.js +114 -0
- package/dist/esm/watch/schema-watcher.js +26 -7
- package/package.json +1 -1
- package/dist/cjs/performance/query-analyzer.d.ts +0 -89
- package/dist/cjs/performance/query-analyzer.js +0 -263
- package/dist/esm/performance/query-analyzer.d.ts +0 -89
- package/dist/esm/performance/query-analyzer.js +0 -260
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.analyze = analyze;
|
|
4
|
-
const chalk_1 = require("chalk");
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
5
8
|
const noormme_js_1 = require("../../noormme.js");
|
|
6
9
|
async function analyze(options) {
|
|
7
10
|
console.log(chalk_1.default.blue.bold('\n🔍 NOORMME Query Analysis - Intelligent Performance Insights\n'));
|
|
@@ -1,15 +1,53 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
2
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
39
|
exports.generate = generate;
|
|
4
40
|
const fs_1 = require("fs");
|
|
5
|
-
const path = require("path");
|
|
6
|
-
const chalk_1 = require("chalk");
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
7
43
|
const noormme_js_1 = require("../../noormme.js");
|
|
44
|
+
const security_validator_js_1 = require("../../util/security-validator.js");
|
|
8
45
|
async function generate(options = {}) {
|
|
9
46
|
console.log(chalk_1.default.blue.bold('\n🔧 NOORMME Code Generation - Automating TypeScript & Repositories\n'));
|
|
10
47
|
try {
|
|
11
|
-
//
|
|
12
|
-
const
|
|
48
|
+
// SECURITY: Validate and sanitize database path to prevent path traversal attacks
|
|
49
|
+
const databasePathInput = options.database || process.env.DATABASE_PATH || './database.sqlite';
|
|
50
|
+
const databasePath = (0, security_validator_js_1.sanitizeDatabasePath)(databasePathInput);
|
|
13
51
|
const db = new noormme_js_1.NOORMME({
|
|
14
52
|
dialect: 'sqlite',
|
|
15
53
|
connection: {
|
|
@@ -22,7 +60,9 @@ async function generate(options = {}) {
|
|
|
22
60
|
});
|
|
23
61
|
await db.initialize();
|
|
24
62
|
const schemaInfo = await db.getSchemaInfo();
|
|
63
|
+
// SECURITY: Validate output directory to prevent path traversal attacks
|
|
25
64
|
const outputDir = options.output || './generated';
|
|
65
|
+
(0, security_validator_js_1.validateOutputDirectory)(outputDir);
|
|
26
66
|
const format = options.format || 'dts';
|
|
27
67
|
console.log(chalk_1.default.gray(`📁 Output directory: ${outputDir}`));
|
|
28
68
|
console.log(chalk_1.default.gray(`📊 Discovered ${schemaInfo.tables.length} tables\n`));
|
|
@@ -186,11 +226,11 @@ function mapColumnToTsType(column) {
|
|
|
186
226
|
}
|
|
187
227
|
// JSON types
|
|
188
228
|
if (type.includes('json')) {
|
|
189
|
-
return 'Record<string,
|
|
229
|
+
return 'Record<string, unknown>';
|
|
190
230
|
}
|
|
191
231
|
// Array types
|
|
192
232
|
if (type.includes('array') || type.includes('[]')) {
|
|
193
|
-
return '
|
|
233
|
+
return 'unknown[]';
|
|
194
234
|
}
|
|
195
235
|
// UUID types
|
|
196
236
|
if (type.includes('uuid')) {
|
|
@@ -201,11 +241,11 @@ function mapColumnToTsType(column) {
|
|
|
201
241
|
}
|
|
202
242
|
function getPrimaryKeyType(table) {
|
|
203
243
|
if (!table.primaryKey || table.primaryKey.length === 0) {
|
|
204
|
-
return '
|
|
244
|
+
return 'unknown';
|
|
205
245
|
}
|
|
206
246
|
if (table.primaryKey.length === 1) {
|
|
207
247
|
const pkColumn = table.columns.find(col => col.name === table.primaryKey[0]);
|
|
208
|
-
return pkColumn ? mapColumnToTsType(pkColumn) : '
|
|
248
|
+
return pkColumn ? mapColumnToTsType(pkColumn) : 'unknown';
|
|
209
249
|
}
|
|
210
250
|
// Composite primary key
|
|
211
251
|
const types = table.primaryKey.map(pkCol => {
|
|
@@ -1,16 +1,57 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
2
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
39
|
exports.init = init;
|
|
4
|
-
const inquirer_1 = require("inquirer");
|
|
40
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
5
41
|
const fs_1 = require("fs");
|
|
6
|
-
const path = require("path");
|
|
7
|
-
const chalk_1 = require("chalk");
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
44
|
+
const security_validator_js_1 = require("../../util/security-validator.js");
|
|
8
45
|
async function init(options) {
|
|
9
46
|
console.log(chalk_1.default.blue.bold('\n🎯 NOORMME Zero-Configuration Setup\n'));
|
|
10
47
|
console.log(chalk_1.default.gray('Setting up NOORMME with complete SQLite automation...\n'));
|
|
11
48
|
try {
|
|
12
|
-
//
|
|
13
|
-
const
|
|
49
|
+
// SECURITY: Validate and sanitize database path to prevent path traversal attacks
|
|
50
|
+
const databasePathInput = options.database || './database.sqlite';
|
|
51
|
+
const databasePath = (0, security_validator_js_1.sanitizeDatabasePath)(databasePathInput);
|
|
52
|
+
// SECURITY: Validate output directory to prevent path traversal attacks
|
|
53
|
+
const outputDir = options.output || 'lib';
|
|
54
|
+
(0, security_validator_js_1.validateOutputDirectory)(outputDir);
|
|
14
55
|
console.log(chalk_1.default.blue('🔍 Detecting existing SQLite database...'));
|
|
15
56
|
// Check if database exists
|
|
16
57
|
const dbExists = await checkDatabaseExists(databasePath);
|
|
@@ -57,7 +98,6 @@ async function init(options) {
|
|
|
57
98
|
return;
|
|
58
99
|
}
|
|
59
100
|
// Generate files with automation focus
|
|
60
|
-
const outputDir = options.output || 'lib';
|
|
61
101
|
await generateDbFile(databasePath, outputDir, options.force, autoOptimize, autoIndex);
|
|
62
102
|
await generateEnvExample(databasePath);
|
|
63
103
|
await generateAutomationConfig(databasePath, autoOptimize, autoIndex);
|
|
@@ -122,7 +162,7 @@ async function generateDbFile(databasePath, outputDir, force, autoOptimize, auto
|
|
|
122
162
|
|
|
123
163
|
// NOORMME with complete SQLite automation
|
|
124
164
|
// Automatically discovers schema, generates types, and optimizes performance
|
|
125
|
-
|
|
165
|
+
const database = new NOORMME({
|
|
126
166
|
dialect: 'sqlite',
|
|
127
167
|
connection: { database: '${databasePath}' },
|
|
128
168
|
|
|
@@ -156,7 +196,7 @@ export const db = new NOORMME({
|
|
|
156
196
|
|
|
157
197
|
// Initialize with complete automation
|
|
158
198
|
export async function initializeDatabase() {
|
|
159
|
-
await
|
|
199
|
+
await database.initialize()
|
|
160
200
|
console.log('🎉 NOORMME initialized with complete SQLite automation!')
|
|
161
201
|
console.log('✅ Schema discovered automatically')
|
|
162
202
|
console.log('✅ Types generated automatically')
|
|
@@ -165,32 +205,32 @@ export async function initializeDatabase() {
|
|
|
165
205
|
|
|
166
206
|
// Get a repository for any table (auto-generated)
|
|
167
207
|
export function getRepository<T>(tableName: string) {
|
|
168
|
-
return
|
|
208
|
+
return database.getRepository<T>(tableName)
|
|
169
209
|
}
|
|
170
210
|
|
|
171
211
|
// Get Kysely instance for complex queries
|
|
172
212
|
export function getKysely() {
|
|
173
|
-
return
|
|
213
|
+
return database.getKysely()
|
|
174
214
|
}
|
|
175
215
|
|
|
176
216
|
// Performance monitoring
|
|
177
217
|
export async function getPerformanceMetrics() {
|
|
178
|
-
return await
|
|
218
|
+
return await database.getSQLitePerformanceMetrics()
|
|
179
219
|
}
|
|
180
220
|
|
|
181
221
|
// Get optimization recommendations
|
|
182
222
|
export async function getOptimizationRecommendations() {
|
|
183
|
-
return await
|
|
223
|
+
return await database.getSQLiteIndexRecommendations()
|
|
184
224
|
}
|
|
185
225
|
|
|
186
226
|
// Apply optimizations
|
|
187
227
|
export async function applyOptimizations() {
|
|
188
|
-
return await
|
|
228
|
+
return await database.applySQLiteOptimizations()
|
|
189
229
|
}
|
|
190
230
|
|
|
191
231
|
// Close database connections
|
|
192
232
|
export async function closeDatabase() {
|
|
193
|
-
await
|
|
233
|
+
await database.close()
|
|
194
234
|
}
|
|
195
235
|
`;
|
|
196
236
|
// Ensure directory exists
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.inspect = inspect;
|
|
4
|
-
const chalk_1 = require("chalk");
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
5
8
|
const noormme_js_1 = require("../../noormme.js");
|
|
9
|
+
const security_validator_js_1 = require("../../util/security-validator.js");
|
|
6
10
|
async function inspect(tableName, options = {}) {
|
|
7
11
|
console.log(chalk_1.default.blue.bold('\n🔍 NOORMME Schema Inspection - Intelligent Database Discovery\n'));
|
|
8
12
|
try {
|
|
9
|
-
//
|
|
10
|
-
const
|
|
13
|
+
// SECURITY: Validate and sanitize database path to prevent path traversal attacks
|
|
14
|
+
const databasePathInput = options.database || process.env.DATABASE_PATH || './database.sqlite';
|
|
15
|
+
const databasePath = (0, security_validator_js_1.sanitizeDatabasePath)(databasePathInput);
|
|
11
16
|
const db = new noormme_js_1.NOORMME({
|
|
12
17
|
dialect: 'sqlite',
|
|
13
18
|
connection: {
|
|
@@ -22,6 +27,8 @@ async function inspect(tableName, options = {}) {
|
|
|
22
27
|
console.log(chalk_1.default.gray(`📁 Database: ${databasePath}\n`));
|
|
23
28
|
const schemaInfo = await db.getSchemaInfo();
|
|
24
29
|
if (tableName) {
|
|
30
|
+
// SECURITY: Validate table name to prevent SQL injection
|
|
31
|
+
(0, security_validator_js_1.validateIdentifier)(tableName, 'table name');
|
|
25
32
|
// Show specific table with automation insights
|
|
26
33
|
const table = schemaInfo.tables.find(t => t.name === tableName);
|
|
27
34
|
if (!table) {
|
|
@@ -1,10 +1,46 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
2
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
39
|
exports.migrate = migrate;
|
|
4
|
-
const chalk_1 = require("chalk");
|
|
40
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
5
41
|
const noormme_js_1 = require("../../noormme.js");
|
|
6
42
|
const fs_1 = require("fs");
|
|
7
|
-
const path = require("path");
|
|
43
|
+
const path = __importStar(require("path"));
|
|
8
44
|
async function migrate(options) {
|
|
9
45
|
console.log(chalk_1.default.blue.bold('\n🔄 NOORMME Migration Management - Automated Schema Evolution\n'));
|
|
10
46
|
try {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.optimize = optimize;
|
|
4
|
-
const chalk_1 = require("chalk");
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
5
8
|
const noormme_js_1 = require("../../noormme.js");
|
|
6
9
|
async function optimize(options) {
|
|
7
10
|
console.log(chalk_1.default.blue.bold('\n⚡ NOORMME SQLite Optimization - Automating Performance\n'));
|
|
@@ -1,10 +1,46 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
2
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
39
|
exports.status = status;
|
|
4
|
-
const chalk_1 = require("chalk");
|
|
40
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
5
41
|
const noormme_js_1 = require("../../noormme.js");
|
|
6
42
|
const fs_1 = require("fs");
|
|
7
|
-
const path = require("path");
|
|
43
|
+
const path = __importStar(require("path"));
|
|
8
44
|
async function status(options) {
|
|
9
45
|
console.log(chalk_1.default.blue.bold('\n📊 NOORMME Status - Automation Dashboard\n'));
|
|
10
46
|
try {
|
|
@@ -212,10 +248,10 @@ async function getAutomationStatus(db) {
|
|
|
212
248
|
try {
|
|
213
249
|
const config = db.config;
|
|
214
250
|
return {
|
|
215
|
-
autoOptimization: config.
|
|
251
|
+
autoOptimization: config.automation?.enableAutoOptimization ?? true,
|
|
216
252
|
queryAnalysis: config.performance?.enableQueryOptimization ?? true,
|
|
217
|
-
autoIndexing: config.
|
|
218
|
-
schemaMonitoring: config.
|
|
253
|
+
autoIndexing: config.automation?.enableIndexRecommendations ?? true,
|
|
254
|
+
schemaMonitoring: config.automation?.enableSchemaWatcher ?? false
|
|
219
255
|
};
|
|
220
256
|
}
|
|
221
257
|
catch {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.watch = watch;
|
|
4
|
-
const chalk_1 = require("chalk");
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
5
8
|
const noormme_js_1 = require("../../noormme.js");
|
|
6
9
|
async function watch(options) {
|
|
7
10
|
console.log(chalk_1.default.blue.bold('\n👁️ NOORMME Schema Watcher - Continuous Automation\n'));
|
package/dist/cjs/cli/index.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
3
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
7
|
const commander_1 = require("commander");
|
|
5
|
-
const chalk_1 = require("chalk");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
6
9
|
const init_js_1 = require("./commands/init.js");
|
|
7
10
|
const inspect_js_1 = require("./commands/inspect.js");
|
|
8
11
|
const generate_js_1 = require("./commands/generate.js");
|
|
@@ -14,30 +14,24 @@ class DatabaseIntrospector {
|
|
|
14
14
|
* Get all tables in the database
|
|
15
15
|
*/
|
|
16
16
|
async getTables() {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}));
|
|
28
|
-
}
|
|
29
|
-
catch (error) {
|
|
30
|
-
console.warn('SQLite table discovery failed:', error);
|
|
31
|
-
throw new Error('Unable to introspect database tables. SQLite database required.');
|
|
32
|
-
}
|
|
17
|
+
// SQLite
|
|
18
|
+
const sqliteTables = await this.db
|
|
19
|
+
.selectFrom('sqlite_master')
|
|
20
|
+
.select('name')
|
|
21
|
+
.where('type', '=', 'table')
|
|
22
|
+
.where('name', 'not like', 'sqlite_%')
|
|
23
|
+
.execute();
|
|
24
|
+
return sqliteTables.map(t => ({
|
|
25
|
+
name: t.name
|
|
26
|
+
}));
|
|
33
27
|
}
|
|
34
28
|
/**
|
|
35
29
|
* Get columns for a specific table
|
|
36
30
|
*/
|
|
37
31
|
async getColumns(tableName) {
|
|
38
32
|
try {
|
|
39
|
-
// SQLite - use raw SQL for
|
|
40
|
-
const result = await (0, sql_js_1.sql) `
|
|
33
|
+
// SQLite - use raw SQL for PRAGMA table_info
|
|
34
|
+
const result = await (0, sql_js_1.sql) `PRAGMA table_info(${sql_js_1.sql.lit(tableName)})`.execute(this.db);
|
|
41
35
|
const sqliteColumns = result.rows;
|
|
42
36
|
return sqliteColumns.map((col) => ({
|
|
43
37
|
name: col.name,
|
|
@@ -50,7 +44,8 @@ class DatabaseIntrospector {
|
|
|
50
44
|
}
|
|
51
45
|
catch (error) {
|
|
52
46
|
console.warn('SQLite column discovery failed:', error);
|
|
53
|
-
|
|
47
|
+
// Return empty array instead of throwing for non-existent tables
|
|
48
|
+
return [];
|
|
54
49
|
}
|
|
55
50
|
}
|
|
56
51
|
/**
|
|
@@ -65,8 +60,8 @@ class DatabaseIntrospector {
|
|
|
65
60
|
*/
|
|
66
61
|
async getForeignKeys(tableName) {
|
|
67
62
|
try {
|
|
68
|
-
// SQLite - use raw SQL for
|
|
69
|
-
const result = await (0, sql_js_1.sql) `
|
|
63
|
+
// SQLite - use raw SQL for PRAGMA foreign_key_list
|
|
64
|
+
const result = await (0, sql_js_1.sql) `PRAGMA foreign_key_list(${sql_js_1.sql.lit(tableName)})`.execute(this.db);
|
|
70
65
|
const sqliteFks = result.rows;
|
|
71
66
|
return sqliteFks.map((fk) => ({
|
|
72
67
|
name: `fk_${tableName}_${fk.from}`,
|
|
@@ -40,28 +40,17 @@ class SqliteIntrospector extends database_introspector_js_1.DatabaseIntrospector
|
|
|
40
40
|
}
|
|
41
41
|
async #getTableMetadata(options) {
|
|
42
42
|
const tablesResult = await this.#tablesQuery(this.#db, options).execute();
|
|
43
|
-
|
|
44
|
-
.with('table_list', (qb) => this.#tablesQuery(qb, options))
|
|
45
|
-
.selectFrom([
|
|
46
|
-
'table_list as tl',
|
|
47
|
-
(0, sql_js_1.sql) `pragma_table_info(tl.name)`.as('p'),
|
|
48
|
-
])
|
|
49
|
-
.select([
|
|
50
|
-
'tl.name as table',
|
|
51
|
-
'p.cid',
|
|
52
|
-
'p.name',
|
|
53
|
-
'p.type',
|
|
54
|
-
'p.notnull',
|
|
55
|
-
'p.dflt_value',
|
|
56
|
-
'p.pk',
|
|
57
|
-
])
|
|
58
|
-
.orderBy('tl.name')
|
|
59
|
-
.orderBy('p.cid')
|
|
60
|
-
.execute();
|
|
43
|
+
// Get column metadata for each table separately since PRAGMA doesn't work in joins
|
|
61
44
|
const columnsByTable = {};
|
|
62
|
-
for (const
|
|
63
|
-
|
|
64
|
-
|
|
45
|
+
for (const table of tablesResult) {
|
|
46
|
+
try {
|
|
47
|
+
const columns = await (0, sql_js_1.sql) `PRAGMA table_info(${sql_js_1.sql.lit(table.name)})`.execute(this.#db);
|
|
48
|
+
columnsByTable[table.name] = columns.rows;
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
console.warn(`Failed to get columns for table ${table.name}:`, error);
|
|
52
|
+
columnsByTable[table.name] = [];
|
|
53
|
+
}
|
|
65
54
|
}
|
|
66
55
|
return tablesResult.map(({ name, sql, type }) => {
|
|
67
56
|
// Enhanced auto-increment detection
|
|
@@ -182,7 +171,7 @@ class SqliteIntrospector extends database_introspector_js_1.DatabaseIntrospector
|
|
|
182
171
|
}
|
|
183
172
|
async getColumns(tableName) {
|
|
184
173
|
try {
|
|
185
|
-
// SQLite - use raw SQL for
|
|
174
|
+
// SQLite - use raw SQL for PRAGMA table_info
|
|
186
175
|
const result = await (0, sql_js_1.sql) `PRAGMA table_info(${sql_js_1.sql.lit(tableName)})`.execute(this.#db);
|
|
187
176
|
const sqliteColumns = result.rows;
|
|
188
177
|
return sqliteColumns.map((col) => ({
|
|
@@ -201,7 +190,7 @@ class SqliteIntrospector extends database_introspector_js_1.DatabaseIntrospector
|
|
|
201
190
|
}
|
|
202
191
|
async getIndexes(tableName) {
|
|
203
192
|
try {
|
|
204
|
-
// SQLite - use raw SQL for
|
|
193
|
+
// SQLite - use raw SQL for PRAGMA index_list
|
|
205
194
|
const result = await (0, sql_js_1.sql) `PRAGMA index_list(${sql_js_1.sql.lit(tableName)})`.execute(this.#db);
|
|
206
195
|
const sqliteIndexes = result.rows;
|
|
207
196
|
return sqliteIndexes.map((idx) => ({
|
|
@@ -217,7 +206,7 @@ class SqliteIntrospector extends database_introspector_js_1.DatabaseIntrospector
|
|
|
217
206
|
}
|
|
218
207
|
async getForeignKeys(tableName) {
|
|
219
208
|
try {
|
|
220
|
-
// SQLite - use raw SQL for
|
|
209
|
+
// SQLite - use raw SQL for PRAGMA foreign_key_list
|
|
221
210
|
const result = await (0, sql_js_1.sql) `PRAGMA foreign_key_list(${sql_js_1.sql.lit(tableName)})`.execute(this.#db);
|
|
222
211
|
const sqliteFks = result.rows;
|
|
223
212
|
return sqliteFks.map((fk) => ({
|
|
@@ -17,6 +17,10 @@ export declare class DynamicModule<DB> {
|
|
|
17
17
|
* create an SQL injection vulnerability. Always __always__ validate the user
|
|
18
18
|
* input before passing it to this method.
|
|
19
19
|
*
|
|
20
|
+
* SECURITY: This method now includes built-in validation to prevent SQL injection
|
|
21
|
+
* through malicious column references. However, you should still validate that
|
|
22
|
+
* the column reference is from a trusted source or whitelist of allowed columns.
|
|
23
|
+
*
|
|
20
24
|
* There are couple of examples below for some use cases, but you can pass
|
|
21
25
|
* `ref` to other methods as well. If the types allow you to pass a `ref`
|
|
22
26
|
* value to some place, it should work.
|
|
@@ -29,6 +33,12 @@ export declare class DynamicModule<DB> {
|
|
|
29
33
|
* async function someQuery(filterColumn: string, filterValue: string) {
|
|
30
34
|
* const { ref } = db.dynamic
|
|
31
35
|
*
|
|
36
|
+
* // Validate input against a whitelist of allowed columns
|
|
37
|
+
* const allowedColumns = ['first_name', 'last_name', 'email']
|
|
38
|
+
* if (!allowedColumns.includes(filterColumn)) {
|
|
39
|
+
* throw new Error('Invalid column')
|
|
40
|
+
* }
|
|
41
|
+
*
|
|
32
42
|
* return await db
|
|
33
43
|
* .selectFrom('person')
|
|
34
44
|
* .selectAll()
|
|
@@ -46,6 +56,12 @@ export declare class DynamicModule<DB> {
|
|
|
46
56
|
* async function someQuery(orderBy: string) {
|
|
47
57
|
* const { ref } = db.dynamic
|
|
48
58
|
*
|
|
59
|
+
* // Validate against allowed columns
|
|
60
|
+
* const allowedColumns = ['first_name', 'last_name', 'created_at']
|
|
61
|
+
* if (!allowedColumns.includes(orderBy)) {
|
|
62
|
+
* throw new Error('Invalid order column')
|
|
63
|
+
* }
|
|
64
|
+
*
|
|
49
65
|
* return await db
|
|
50
66
|
* .selectFrom('person')
|
|
51
67
|
* .select('person.first_name as fn')
|
|
@@ -92,6 +108,10 @@ export declare class DynamicModule<DB> {
|
|
|
92
108
|
*
|
|
93
109
|
* The type `T` is allowed to be a union of multiple tables.
|
|
94
110
|
*
|
|
111
|
+
* SECURITY: This method now includes built-in validation to prevent SQL injection
|
|
112
|
+
* through malicious table references. However, you should still validate that
|
|
113
|
+
* the table reference is from a trusted source or whitelist of allowed tables.
|
|
114
|
+
*
|
|
95
115
|
* <!-- siteExample("select", "Generic find query", 130) -->
|
|
96
116
|
*
|
|
97
117
|
* A generic type-safe helper function for finding a row by a column value:
|