dbdock 1.1.15 → 1.1.17

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.
Files changed (43) hide show
  1. package/README.md +473 -580
  2. package/dist/cli/commands/analyze.d.ts +1 -0
  3. package/dist/cli/commands/analyze.js +135 -0
  4. package/dist/cli/commands/analyze.js.map +1 -0
  5. package/dist/cli/commands/cross-migrate.d.ts +11 -0
  6. package/dist/cli/commands/cross-migrate.js +307 -0
  7. package/dist/cli/commands/cross-migrate.js.map +1 -0
  8. package/dist/cli/index.js +20 -0
  9. package/dist/cli/index.js.map +1 -1
  10. package/dist/migration/analyzers/mongodb.analyzer.d.ts +3 -0
  11. package/dist/migration/analyzers/mongodb.analyzer.js +208 -0
  12. package/dist/migration/analyzers/mongodb.analyzer.js.map +1 -0
  13. package/dist/migration/analyzers/postgres.analyzer.d.ts +3 -0
  14. package/dist/migration/analyzers/postgres.analyzer.js +176 -0
  15. package/dist/migration/analyzers/postgres.analyzer.js.map +1 -0
  16. package/dist/migration/config.manager.d.ts +3 -0
  17. package/dist/migration/config.manager.js +80 -0
  18. package/dist/migration/config.manager.js.map +1 -0
  19. package/dist/migration/engines/migration.engine.d.ts +6 -0
  20. package/dist/migration/engines/migration.engine.js +62 -0
  21. package/dist/migration/engines/migration.engine.js.map +1 -0
  22. package/dist/migration/engines/mongo-to-postgres.engine.d.ts +2 -0
  23. package/dist/migration/engines/mongo-to-postgres.engine.js +409 -0
  24. package/dist/migration/engines/mongo-to-postgres.engine.js.map +1 -0
  25. package/dist/migration/engines/postgres-to-mongo.engine.d.ts +2 -0
  26. package/dist/migration/engines/postgres-to-mongo.engine.js +192 -0
  27. package/dist/migration/engines/postgres-to-mongo.engine.js.map +1 -0
  28. package/dist/migration/mappers/mongo-to-postgres.mapper.d.ts +2 -0
  29. package/dist/migration/mappers/mongo-to-postgres.mapper.js +263 -0
  30. package/dist/migration/mappers/mongo-to-postgres.mapper.js.map +1 -0
  31. package/dist/migration/mappers/postgres-to-mongo.mapper.d.ts +2 -0
  32. package/dist/migration/mappers/postgres-to-mongo.mapper.js +174 -0
  33. package/dist/migration/mappers/postgres-to-mongo.mapper.js.map +1 -0
  34. package/dist/migration/reference.detector.d.ts +2 -0
  35. package/dist/migration/reference.detector.js +57 -0
  36. package/dist/migration/reference.detector.js.map +1 -0
  37. package/dist/migration/type.mapper.d.ts +12 -0
  38. package/dist/migration/type.mapper.js +197 -0
  39. package/dist/migration/type.mapper.js.map +1 -0
  40. package/dist/migration/types.d.ts +183 -0
  41. package/dist/migration/types.js +11 -0
  42. package/dist/migration/types.js.map +1 -0
  43. package/package.json +11 -2
@@ -0,0 +1,208 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseMongoUrl = parseMongoUrl;
4
+ exports.analyzeMongoDB = analyzeMongoDB;
5
+ const mongodb_1 = require("mongodb");
6
+ const type_mapper_1 = require("../type.mapper");
7
+ const SAMPLE_SIZE = 5000;
8
+ const MAX_SAMPLE_VALUES = 5;
9
+ function parseMongoUrl(urlString) {
10
+ const url = new URL(urlString);
11
+ if (url.protocol !== 'mongodb:' && url.protocol !== 'mongodb+srv:') {
12
+ throw new Error(`Invalid protocol "${url.protocol}". Expected "mongodb://" or "mongodb+srv://"`);
13
+ }
14
+ const database = url.pathname.replace(/^\//, '') || 'test';
15
+ return {
16
+ type: 'mongodb',
17
+ url: urlString,
18
+ database,
19
+ host: url.hostname || 'localhost',
20
+ port: parseInt(url.port || '27017'),
21
+ };
22
+ }
23
+ async function analyzeMongoDB(connectionUrl, sampleSize = SAMPLE_SIZE) {
24
+ const parsed = parseMongoUrl(connectionUrl);
25
+ const client = new mongodb_1.MongoClient(connectionUrl);
26
+ try {
27
+ await client.connect();
28
+ const db = client.db(parsed.database);
29
+ const collectionNames = await getCollectionNames(db);
30
+ const collections = [];
31
+ let totalDocuments = 0;
32
+ for (const name of collectionNames) {
33
+ const analysis = await analyzeCollection(db, name, sampleSize);
34
+ collections.push(analysis);
35
+ totalDocuments += analysis.documentCount;
36
+ }
37
+ return {
38
+ database: parsed.database,
39
+ type: 'mongodb',
40
+ collections,
41
+ totalDocuments,
42
+ };
43
+ }
44
+ finally {
45
+ await client.close();
46
+ }
47
+ }
48
+ async function getCollectionNames(db) {
49
+ const collections = await db.listCollections().toArray();
50
+ return collections
51
+ .filter((c) => c.type === 'collection')
52
+ .map((c) => c.name)
53
+ .filter((n) => !n.startsWith('system.'));
54
+ }
55
+ async function analyzeCollection(db, collectionName, sampleSize) {
56
+ const collection = db.collection(collectionName);
57
+ const documentCount = await collection.countDocuments();
58
+ let documents;
59
+ if (documentCount <= sampleSize) {
60
+ documents = await collection.find({}).toArray();
61
+ }
62
+ else {
63
+ documents = await collection.aggregate([{ $sample: { size: sampleSize } }]).toArray();
64
+ }
65
+ const fieldMap = new Map();
66
+ const sampledCount = documents.length;
67
+ for (const doc of documents) {
68
+ analyzeDocument(doc, '', fieldMap, 0);
69
+ }
70
+ const fields = buildFieldInfos(fieldMap, sampledCount, documentCount);
71
+ const indexes = await collection.indexes().catch(() => []);
72
+ const indexInfo = indexes.map((idx) => ({
73
+ name: idx.name,
74
+ key: idx.key,
75
+ unique: idx.unique || false,
76
+ }));
77
+ return {
78
+ name: collectionName,
79
+ documentCount,
80
+ fields,
81
+ indexes: indexInfo,
82
+ };
83
+ }
84
+ function getOrCreateAccumulator(map, path, name, depth) {
85
+ if (!map.has(path)) {
86
+ map.set(path, {
87
+ name,
88
+ path,
89
+ typeCounts: {},
90
+ count: 0,
91
+ isArray: false,
92
+ isObjectId: false,
93
+ isNestedObject: false,
94
+ sampleValues: [],
95
+ depth,
96
+ children: new Map(),
97
+ arrayElementTypes: new Set(),
98
+ });
99
+ }
100
+ return map.get(path);
101
+ }
102
+ function analyzeDocument(doc, prefix, fieldMap, depth) {
103
+ if (!doc || typeof doc !== 'object' || Array.isArray(doc))
104
+ return;
105
+ for (const [key, value] of Object.entries(doc)) {
106
+ const path = prefix ? `${prefix}.${key}` : key;
107
+ const acc = getOrCreateAccumulator(fieldMap, path, key, depth);
108
+ acc.count++;
109
+ const fieldType = (0, type_mapper_1.detectMongoFieldType)(value);
110
+ acc.typeCounts[fieldType] = (acc.typeCounts[fieldType] || 0) + 1;
111
+ if (acc.sampleValues.length < MAX_SAMPLE_VALUES) {
112
+ acc.sampleValues.push(summarizeValue(value));
113
+ }
114
+ if (fieldType === 'objectId') {
115
+ acc.isObjectId = true;
116
+ }
117
+ if (fieldType === 'array' && Array.isArray(value)) {
118
+ acc.isArray = true;
119
+ for (const element of value.slice(0, 100)) {
120
+ const elType = (0, type_mapper_1.detectMongoFieldType)(element);
121
+ acc.arrayElementTypes.add(elType);
122
+ if (elType === 'object' && element && typeof element === 'object') {
123
+ analyzeDocument(element, path + '[]', fieldMap, depth + 1);
124
+ }
125
+ }
126
+ }
127
+ if (fieldType === 'object' && value && !isSpecialBsonType(value)) {
128
+ acc.isNestedObject = true;
129
+ analyzeDocument(value, path, fieldMap, depth + 1);
130
+ }
131
+ }
132
+ }
133
+ function isSpecialBsonType(value) {
134
+ if (!value || typeof value !== 'object')
135
+ return false;
136
+ return !!(value._bsontype || value instanceof mongodb_1.ObjectId || value instanceof Date);
137
+ }
138
+ function summarizeValue(value) {
139
+ if (value === null || value === undefined)
140
+ return value;
141
+ if (typeof value === 'string')
142
+ return value.length > 50 ? value.slice(0, 50) + '...' : value;
143
+ if (typeof value === 'number' || typeof value === 'boolean')
144
+ return value;
145
+ if (value instanceof Date)
146
+ return value.toISOString();
147
+ if (value instanceof mongodb_1.ObjectId || value?._bsontype === 'ObjectId')
148
+ return value.toString();
149
+ if (Array.isArray(value))
150
+ return `[Array(${value.length})]`;
151
+ if (typeof value === 'object')
152
+ return `{Object(${Object.keys(value).length} keys)}`;
153
+ return String(value);
154
+ }
155
+ function buildFieldInfos(fieldMap, sampledCount, totalCount) {
156
+ const topLevelFields = [];
157
+ const topLevelEntries = Array.from(fieldMap.entries()).filter(([path]) => !path.includes('.'));
158
+ for (const [, acc] of topLevelEntries) {
159
+ const field = accumulatorToFieldInfo(acc, fieldMap, sampledCount, totalCount);
160
+ topLevelFields.push(field);
161
+ }
162
+ topLevelFields.sort((a, b) => b.frequency - a.frequency);
163
+ return topLevelFields;
164
+ }
165
+ function accumulatorToFieldInfo(acc, fieldMap, sampledCount, totalCount) {
166
+ const frequency = sampledCount > 0
167
+ ? Math.round((acc.count / sampledCount) * 100 * 100) / 100
168
+ : 0;
169
+ const nestedFields = [];
170
+ const childPrefix = acc.path + '.';
171
+ const arrayChildPrefix = acc.path + '[].';
172
+ for (const [path, childAcc] of fieldMap.entries()) {
173
+ if (path.startsWith(childPrefix) || path.startsWith(arrayChildPrefix)) {
174
+ const remaining = path.startsWith(childPrefix)
175
+ ? path.slice(childPrefix.length)
176
+ : path.slice(arrayChildPrefix.length);
177
+ if (!remaining.includes('.') && !remaining.includes('[]')) {
178
+ nestedFields.push(accumulatorToFieldInfo(childAcc, fieldMap, sampledCount, totalCount));
179
+ }
180
+ }
181
+ }
182
+ nestedFields.sort((a, b) => b.frequency - a.frequency);
183
+ const possibleReference = acc.isObjectId && acc.name !== '_id'
184
+ ? guessReferenceFromName(acc.name)
185
+ : undefined;
186
+ return {
187
+ name: acc.name,
188
+ path: acc.path,
189
+ types: acc.typeCounts,
190
+ totalCount: Math.round((acc.count / sampledCount) * totalCount),
191
+ frequency,
192
+ isArray: acc.isArray,
193
+ isObjectId: acc.isObjectId,
194
+ isNestedObject: acc.isNestedObject,
195
+ nestedFields: nestedFields.length > 0 ? nestedFields : undefined,
196
+ arrayElementType: acc.arrayElementTypes.size > 0
197
+ ? Array.from(acc.arrayElementTypes).join(' | ')
198
+ : undefined,
199
+ possibleReference,
200
+ sampleValues: acc.sampleValues,
201
+ depth: acc.depth,
202
+ };
203
+ }
204
+ function guessReferenceFromName(fieldName) {
205
+ const cleaned = fieldName.replace(/(_id|Id)$/, '');
206
+ return cleaned || undefined;
207
+ }
208
+ //# sourceMappingURL=mongodb.analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mongodb.analyzer.js","sourceRoot":"","sources":["../../../src/migration/analyzers/mongodb.analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { PgAnalysisResult, ParsedDatabaseUrl } from '../types';
2
+ export declare function parsePostgresUrl(urlString: string): ParsedDatabaseUrl;
3
+ export declare function analyzePostgres(connectionUrl: string): Promise<PgAnalysisResult>;
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parsePostgresUrl = parsePostgresUrl;
4
+ exports.analyzePostgres = analyzePostgres;
5
+ const pg_1 = require("pg");
6
+ function parsePostgresUrl(urlString) {
7
+ const url = new URL(urlString);
8
+ if (url.protocol !== 'postgresql:' && url.protocol !== 'postgres:') {
9
+ throw new Error(`Invalid protocol "${url.protocol}". Expected "postgresql://" or "postgres://"`);
10
+ }
11
+ const database = url.pathname.replace(/^\//, '') || 'postgres';
12
+ return {
13
+ type: 'postgresql',
14
+ url: urlString,
15
+ database,
16
+ host: url.hostname || 'localhost',
17
+ port: parseInt(url.port || '5432'),
18
+ };
19
+ }
20
+ async function analyzePostgres(connectionUrl) {
21
+ const parsed = parsePostgresUrl(connectionUrl);
22
+ const pool = new pg_1.Pool({ connectionString: connectionUrl });
23
+ try {
24
+ const tableNames = await getTableNames(pool);
25
+ const tables = [];
26
+ let totalRows = 0;
27
+ for (const tableName of tableNames) {
28
+ const analysis = await analyzeTable(pool, tableName);
29
+ tables.push(analysis);
30
+ totalRows += analysis.rowCount;
31
+ }
32
+ return {
33
+ database: parsed.database,
34
+ type: 'postgresql',
35
+ tables,
36
+ totalRows,
37
+ };
38
+ }
39
+ finally {
40
+ await pool.end();
41
+ }
42
+ }
43
+ async function getTableNames(pool) {
44
+ const result = await pool.query(`
45
+ SELECT table_name
46
+ FROM information_schema.tables
47
+ WHERE table_schema = 'public'
48
+ AND table_type = 'BASE TABLE'
49
+ ORDER BY table_name
50
+ `);
51
+ return result.rows.map((r) => r.table_name);
52
+ }
53
+ async function analyzeTable(pool, tableName) {
54
+ const [columns, foreignKeys, indexes, rowCount] = await Promise.all([
55
+ getColumns(pool, tableName),
56
+ getForeignKeys(pool, tableName),
57
+ getIndexes(pool, tableName),
58
+ getRowCount(pool, tableName),
59
+ ]);
60
+ return {
61
+ name: tableName,
62
+ schema: 'public',
63
+ columns,
64
+ foreignKeys,
65
+ indexes,
66
+ rowCount,
67
+ };
68
+ }
69
+ async function getColumns(pool, tableName) {
70
+ const result = await pool.query(`
71
+ SELECT
72
+ c.column_name,
73
+ c.data_type,
74
+ c.udt_name,
75
+ c.is_nullable,
76
+ c.column_default,
77
+ c.character_maximum_length,
78
+ c.numeric_precision,
79
+ COALESCE(pk.is_pk, false) AS is_primary_key,
80
+ COALESCE(uq.is_unique, false) AS is_unique
81
+ FROM information_schema.columns c
82
+ LEFT JOIN (
83
+ SELECT kcu.column_name, true AS is_pk
84
+ FROM information_schema.table_constraints tc
85
+ JOIN information_schema.key_column_usage kcu
86
+ ON tc.constraint_name = kcu.constraint_name
87
+ AND tc.table_schema = kcu.table_schema
88
+ WHERE tc.table_name = $1
89
+ AND tc.table_schema = 'public'
90
+ AND tc.constraint_type = 'PRIMARY KEY'
91
+ ) pk ON pk.column_name = c.column_name
92
+ LEFT JOIN (
93
+ SELECT kcu.column_name, true AS is_unique
94
+ FROM information_schema.table_constraints tc
95
+ JOIN information_schema.key_column_usage kcu
96
+ ON tc.constraint_name = kcu.constraint_name
97
+ AND tc.table_schema = kcu.table_schema
98
+ WHERE tc.table_name = $1
99
+ AND tc.table_schema = 'public'
100
+ AND tc.constraint_type = 'UNIQUE'
101
+ ) uq ON uq.column_name = c.column_name
102
+ WHERE c.table_name = $1
103
+ AND c.table_schema = 'public'
104
+ ORDER BY c.ordinal_position
105
+ `, [tableName]);
106
+ return result.rows.map((r) => ({
107
+ name: r.column_name,
108
+ dataType: r.data_type,
109
+ udtName: r.udt_name,
110
+ isNullable: r.is_nullable === 'YES',
111
+ columnDefault: r.column_default,
112
+ isPrimaryKey: r.is_primary_key === true,
113
+ isUnique: r.is_unique === true,
114
+ characterMaxLength: r.character_maximum_length,
115
+ numericPrecision: r.numeric_precision,
116
+ }));
117
+ }
118
+ async function getForeignKeys(pool, tableName) {
119
+ const result = await pool.query(`
120
+ SELECT
121
+ tc.constraint_name,
122
+ kcu.column_name,
123
+ ccu.table_name AS referenced_table,
124
+ ccu.column_name AS referenced_column
125
+ FROM information_schema.table_constraints tc
126
+ JOIN information_schema.key_column_usage kcu
127
+ ON tc.constraint_name = kcu.constraint_name
128
+ AND tc.table_schema = kcu.table_schema
129
+ JOIN information_schema.constraint_column_usage ccu
130
+ ON ccu.constraint_name = tc.constraint_name
131
+ AND ccu.table_schema = tc.table_schema
132
+ WHERE tc.table_name = $1
133
+ AND tc.table_schema = 'public'
134
+ AND tc.constraint_type = 'FOREIGN KEY'
135
+ `, [tableName]);
136
+ return result.rows.map((r) => ({
137
+ constraintName: r.constraint_name,
138
+ columnName: r.column_name,
139
+ referencedTable: r.referenced_table,
140
+ referencedColumn: r.referenced_column,
141
+ }));
142
+ }
143
+ async function getIndexes(pool, tableName) {
144
+ const result = await pool.query(`
145
+ SELECT
146
+ i.relname AS index_name,
147
+ array_agg(a.attname ORDER BY k.n) AS columns,
148
+ ix.indisunique AS is_unique,
149
+ ix.indisprimary AS is_primary
150
+ FROM pg_index ix
151
+ JOIN pg_class t ON t.oid = ix.indrelid
152
+ JOIN pg_class i ON i.oid = ix.indexrelid
153
+ JOIN pg_namespace n ON n.oid = t.relnamespace
154
+ CROSS JOIN LATERAL unnest(ix.indkey) WITH ORDINALITY AS k(attnum, n)
155
+ JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = k.attnum
156
+ WHERE t.relname = $1
157
+ AND n.nspname = 'public'
158
+ GROUP BY i.relname, ix.indisunique, ix.indisprimary
159
+ `, [tableName]);
160
+ return result.rows.map((r) => ({
161
+ name: r.index_name,
162
+ columns: r.columns,
163
+ isUnique: r.is_unique,
164
+ isPrimary: r.is_primary,
165
+ }));
166
+ }
167
+ async function getRowCount(pool, tableName) {
168
+ const result = await pool.query(`SELECT reltuples::bigint AS estimate FROM pg_class WHERE relname = $1`, [tableName]);
169
+ const estimate = parseInt(result.rows[0]?.estimate || '0');
170
+ if (estimate < 10000) {
171
+ const exact = await pool.query(`SELECT count(*)::integer AS count FROM "${tableName}"`);
172
+ return parseInt(exact.rows[0]?.count || '0');
173
+ }
174
+ return Math.max(estimate, 0);
175
+ }
176
+ //# sourceMappingURL=postgres.analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres.analyzer.js","sourceRoot":"","sources":["../../../src/migration/analyzers/postgres.analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { MigrationPlan } from './types';
2
+ export declare function exportConfig(plan: MigrationPlan, filePath: string): void;
3
+ export declare function importConfig(filePath: string): MigrationPlan;
@@ -0,0 +1,80 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.exportConfig = exportConfig;
37
+ exports.importConfig = importConfig;
38
+ const fs_1 = require("fs");
39
+ const yaml = __importStar(require("js-yaml"));
40
+ function exportConfig(plan, filePath) {
41
+ const ext = filePath.split('.').pop()?.toLowerCase();
42
+ const data = sanitizePlanForExport(plan);
43
+ if (ext === 'yaml' || ext === 'yml') {
44
+ (0, fs_1.writeFileSync)(filePath, yaml.dump(data, { indent: 2, lineWidth: 120 }));
45
+ }
46
+ else {
47
+ (0, fs_1.writeFileSync)(filePath, JSON.stringify(data, null, 2));
48
+ }
49
+ }
50
+ function importConfig(filePath) {
51
+ if (!(0, fs_1.existsSync)(filePath)) {
52
+ throw new Error(`Config file not found: ${filePath}`);
53
+ }
54
+ const content = (0, fs_1.readFileSync)(filePath, 'utf-8');
55
+ const ext = filePath.split('.').pop()?.toLowerCase();
56
+ let data;
57
+ if (ext === 'yaml' || ext === 'yml') {
58
+ data = yaml.load(content);
59
+ }
60
+ else {
61
+ data = JSON.parse(content);
62
+ }
63
+ if (!data.version || !data.direction || !data.source || !data.target) {
64
+ throw new Error('Invalid migration config: missing required fields');
65
+ }
66
+ return data;
67
+ }
68
+ function sanitizePlanForExport(plan) {
69
+ return {
70
+ version: plan.version,
71
+ direction: plan.direction,
72
+ source: { type: plan.source.type, database: plan.source.database },
73
+ target: { type: plan.target.type, database: plan.target.database },
74
+ tableMappings: plan.tableMappings,
75
+ documentMappings: plan.documentMappings,
76
+ conflicts: plan.conflicts,
77
+ options: plan.options,
78
+ };
79
+ }
80
+ //# sourceMappingURL=config.manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.manager.js","sourceRoot":"","sources":["../../src/migration/config.manager.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,oCASC;AAED,oCAoBC;AAnCD,2BAA6D;AAC7D,8CAAgC;AAGhC,SAAgB,YAAY,CAAC,IAAmB,EAAE,QAAgB;IAChE,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,CAAC;IACrD,MAAM,IAAI,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAEzC,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QACpC,IAAA,kBAAa,EAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IAC1E,CAAC;SAAM,CAAC;QACN,IAAA,kBAAa,EAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAED,SAAgB,YAAY,CAAC,QAAgB;IAC3C,IAAI,CAAC,IAAA,eAAU,EAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,OAAO,GAAG,IAAA,iBAAY,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,CAAC;IAErD,IAAI,IAAS,CAAC;IACd,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QACpC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,OAAO,IAAqB,CAAC;AAC/B,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAmB;IAChD,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE;QAClE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE;QAClE,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;QACvC,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,OAAO,EAAE,IAAI,CAAC,OAAO;KACtB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { MigrationPlan, MigrationResult, MigrationOptions, AnalysisResult, ParsedDatabaseUrl } from '../types';
2
+ export declare function parseDatabaseUrl(url: string): ParsedDatabaseUrl;
3
+ export declare function analyzeDatabase(url: string): Promise<AnalysisResult>;
4
+ export declare function generateMigrationPlan(analysis: AnalysisResult, sourceUrl: string, targetUrl: string, options?: Partial<MigrationOptions>): MigrationPlan;
5
+ export declare function executeMigration(plan: MigrationPlan, onProgress?: (table: string, processed: number, total: number) => void): Promise<MigrationResult>;
6
+ export declare function maskUrl(url: string): string;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseDatabaseUrl = parseDatabaseUrl;
4
+ exports.analyzeDatabase = analyzeDatabase;
5
+ exports.generateMigrationPlan = generateMigrationPlan;
6
+ exports.executeMigration = executeMigration;
7
+ exports.maskUrl = maskUrl;
8
+ const mongodb_analyzer_1 = require("../analyzers/mongodb.analyzer");
9
+ const postgres_analyzer_1 = require("../analyzers/postgres.analyzer");
10
+ const mongo_to_postgres_mapper_1 = require("../mappers/mongo-to-postgres.mapper");
11
+ const postgres_to_mongo_mapper_1 = require("../mappers/postgres-to-mongo.mapper");
12
+ const mongo_to_postgres_engine_1 = require("./mongo-to-postgres.engine");
13
+ const postgres_to_mongo_engine_1 = require("./postgres-to-mongo.engine");
14
+ function parseDatabaseUrl(url) {
15
+ if (url.startsWith('mongodb://') || url.startsWith('mongodb+srv://')) {
16
+ return (0, mongodb_analyzer_1.parseMongoUrl)(url);
17
+ }
18
+ if (url.startsWith('postgresql://') || url.startsWith('postgres://')) {
19
+ return (0, postgres_analyzer_1.parsePostgresUrl)(url);
20
+ }
21
+ throw new Error(`Unsupported database URL. Expected "mongodb://", "mongodb+srv://", "postgresql://", or "postgres://"`);
22
+ }
23
+ async function analyzeDatabase(url) {
24
+ const parsed = parseDatabaseUrl(url);
25
+ if (parsed.type === 'mongodb') {
26
+ return (0, mongodb_analyzer_1.analyzeMongoDB)(url);
27
+ }
28
+ return (0, postgres_analyzer_1.analyzePostgres)(url);
29
+ }
30
+ function generateMigrationPlan(analysis, sourceUrl, targetUrl, options = {}) {
31
+ const targetParsed = parseDatabaseUrl(targetUrl);
32
+ if (analysis.type === 'mongodb' && targetParsed.type === 'postgresql') {
33
+ return (0, mongo_to_postgres_mapper_1.generateMongoToPostgresPlan)(analysis, sourceUrl, targetUrl, options);
34
+ }
35
+ if (analysis.type === 'postgresql' && targetParsed.type === 'mongodb') {
36
+ return (0, postgres_to_mongo_mapper_1.generatePostgresToMongoPlan)(analysis, sourceUrl, targetUrl, options);
37
+ }
38
+ throw new Error(`Unsupported migration direction: ${analysis.type} → ${targetParsed.type}. ` +
39
+ `Supported: MongoDB → PostgreSQL, PostgreSQL → MongoDB`);
40
+ }
41
+ async function executeMigration(plan, onProgress) {
42
+ if (plan.direction === 'mongo_to_postgres') {
43
+ return (0, mongo_to_postgres_engine_1.executeMongoToPostgres)(plan, onProgress);
44
+ }
45
+ if (plan.direction === 'postgres_to_mongo') {
46
+ return (0, postgres_to_mongo_engine_1.executePostgresToMongo)(plan, onProgress);
47
+ }
48
+ throw new Error(`Unsupported migration direction: ${plan.direction}`);
49
+ }
50
+ function maskUrl(url) {
51
+ try {
52
+ const parsed = new URL(url);
53
+ if (parsed.password) {
54
+ parsed.password = '****';
55
+ }
56
+ return parsed.toString();
57
+ }
58
+ catch {
59
+ return url;
60
+ }
61
+ }
62
+ //# sourceMappingURL=migration.engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration.engine.js","sourceRoot":"","sources":["../../../src/migration/engines/migration.engine.ts"],"names":[],"mappings":";;AAeA,4CAUC;AAED,0CAQC;AAED,sDAoBC;AAED,4CAaC;AAED,0BAUC;AA5ED,oEAA8E;AAC9E,sEAAmF;AACnF,kFAAkF;AAClF,kFAAkF;AAClF,yEAAoE;AACpE,yEAAoE;AAEpE,SAAgB,gBAAgB,CAAC,GAAW;IAC1C,IAAI,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACrE,OAAO,IAAA,gCAAa,EAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IACD,IAAI,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QACrE,OAAO,IAAA,oCAAgB,EAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IACD,MAAM,IAAI,KAAK,CACb,sGAAsG,CACvG,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,eAAe,CAAC,GAAW;IAC/C,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAErC,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,IAAA,iCAAc,EAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO,IAAA,mCAAe,EAAC,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED,SAAgB,qBAAqB,CACnC,QAAwB,EACxB,SAAiB,EACjB,SAAiB,EACjB,UAAqC,EAAE;IAEvC,MAAM,YAAY,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAEjD,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,IAAI,YAAY,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QACtE,OAAO,IAAA,sDAA2B,EAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAC9E,CAAC;IAED,IAAI,QAAQ,CAAC,IAAI,KAAK,YAAY,IAAI,YAAY,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACtE,OAAO,IAAA,sDAA2B,EAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,IAAI,KAAK,CACb,oCAAoC,QAAQ,CAAC,IAAI,MAAM,YAAY,CAAC,IAAI,IAAI;QAC5E,uDAAuD,CACxD,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,gBAAgB,CACpC,IAAmB,EACnB,UAAsE;IAEtE,IAAI,IAAI,CAAC,SAAS,KAAK,mBAAmB,EAAE,CAAC;QAC3C,OAAO,IAAA,iDAAsB,EAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAClD,CAAC;IAED,IAAI,IAAI,CAAC,SAAS,KAAK,mBAAmB,EAAE,CAAC;QAC3C,OAAO,IAAA,iDAAsB,EAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,SAAgB,OAAO,CAAC,GAAW;IACjC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpB,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC;QAC3B,CAAC;QACD,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,CAAC;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { MigrationPlan, MigrationResult } from '../types';
2
+ export declare function executeMongoToPostgres(plan: MigrationPlan, onProgress?: (table: string, processed: number, total: number) => void): Promise<MigrationResult>;