dbdock 1.1.16 → 1.1.19

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 (52) hide show
  1. package/README.md +236 -11
  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/cli/utils/config.js +125 -5
  11. package/dist/cli/utils/config.js.map +1 -1
  12. package/dist/config/config.service.js +21 -3
  13. package/dist/config/config.service.js.map +1 -1
  14. package/dist/config/env-url.helper.d.ts +11 -0
  15. package/dist/config/env-url.helper.js +56 -0
  16. package/dist/config/env-url.helper.js.map +1 -0
  17. package/dist/config/secrets.validator.js +5 -1
  18. package/dist/config/secrets.validator.js.map +1 -1
  19. package/dist/migration/analyzers/mongodb.analyzer.d.ts +3 -0
  20. package/dist/migration/analyzers/mongodb.analyzer.js +208 -0
  21. package/dist/migration/analyzers/mongodb.analyzer.js.map +1 -0
  22. package/dist/migration/analyzers/postgres.analyzer.d.ts +3 -0
  23. package/dist/migration/analyzers/postgres.analyzer.js +176 -0
  24. package/dist/migration/analyzers/postgres.analyzer.js.map +1 -0
  25. package/dist/migration/config.manager.d.ts +3 -0
  26. package/dist/migration/config.manager.js +80 -0
  27. package/dist/migration/config.manager.js.map +1 -0
  28. package/dist/migration/engines/migration.engine.d.ts +6 -0
  29. package/dist/migration/engines/migration.engine.js +62 -0
  30. package/dist/migration/engines/migration.engine.js.map +1 -0
  31. package/dist/migration/engines/mongo-to-postgres.engine.d.ts +2 -0
  32. package/dist/migration/engines/mongo-to-postgres.engine.js +409 -0
  33. package/dist/migration/engines/mongo-to-postgres.engine.js.map +1 -0
  34. package/dist/migration/engines/postgres-to-mongo.engine.d.ts +2 -0
  35. package/dist/migration/engines/postgres-to-mongo.engine.js +192 -0
  36. package/dist/migration/engines/postgres-to-mongo.engine.js.map +1 -0
  37. package/dist/migration/mappers/mongo-to-postgres.mapper.d.ts +2 -0
  38. package/dist/migration/mappers/mongo-to-postgres.mapper.js +263 -0
  39. package/dist/migration/mappers/mongo-to-postgres.mapper.js.map +1 -0
  40. package/dist/migration/mappers/postgres-to-mongo.mapper.d.ts +2 -0
  41. package/dist/migration/mappers/postgres-to-mongo.mapper.js +174 -0
  42. package/dist/migration/mappers/postgres-to-mongo.mapper.js.map +1 -0
  43. package/dist/migration/reference.detector.d.ts +2 -0
  44. package/dist/migration/reference.detector.js +57 -0
  45. package/dist/migration/reference.detector.js.map +1 -0
  46. package/dist/migration/type.mapper.d.ts +12 -0
  47. package/dist/migration/type.mapper.js +197 -0
  48. package/dist/migration/type.mapper.js.map +1 -0
  49. package/dist/migration/types.d.ts +183 -0
  50. package/dist/migration/types.js +11 -0
  51. package/dist/migration/types.js.map +1 -0
  52. package/package.json +11 -2
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # DBDock
2
2
 
3
- Stop writing backup scripts. Stop losing sleep over database migrations. DBDock handles PostgreSQL backups, restores, and database copies in one command.
3
+ Stop writing backup scripts. Stop losing sleep over database migrations. DBDock handles PostgreSQL backups, restores, database copies, and cross-database migrations between MongoDB and PostgreSQL in one command.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/dbdock.svg)](https://www.npmjs.com/package/dbdock)
6
6
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
@@ -20,13 +20,14 @@ It's not hard. It's just repetitive. And repetitive stuff should be one command.
20
20
  ## The Fix
21
21
 
22
22
  ```bash
23
- npx dbdock init # One-time setup (takes 30 seconds)
24
- npx dbdock backup # Backup with encryption + compression
25
- npx dbdock restore # Restore from any backup
26
- npx dbdock copydb "db_url_1" "db_url_2" # Copy entire database, zero config
23
+ npx dbdock init # One-time setup (takes 30 seconds)
24
+ npx dbdock backup # Backup with encryption + compression
25
+ npx dbdock restore # Restore from any backup
26
+ npx dbdock copydb "db_url_1" "db_url_2" # Copy entire database, zero config
27
+ npx dbdock migrate "mongo_url" "postgres_url" # Cross-database migration
27
28
  ```
28
29
 
29
- That's it. No shell scripts. No manual uploads. No config files for `copydb`.
30
+ That's it. No shell scripts. No manual uploads. No throwaway migration code.
30
31
 
31
32
  ---
32
33
 
@@ -72,6 +73,8 @@ It asks for your database connection, picks your storage (Local, S3, R2, Cloudin
72
73
  - Config (safe stuff) goes to `dbdock.config.json` — commit this
73
74
  - Secrets go to `.env` — never committed, `.gitignore` updated automatically
74
75
 
76
+ You can also run **without a config file**: set `DBDOCK_DB_URL` (or `DATABASE_URL`) and other env vars and DBDock will use env-only configuration.
77
+
75
78
  ---
76
79
 
77
80
  ### `dbdock backup` — One command, full backup
@@ -258,6 +261,221 @@ Got secrets sitting in `dbdock.config.json` from an older version? This extracts
258
261
 
259
262
  ---
260
263
 
264
+ ## Cross-Database Migration (MongoDB ↔ PostgreSQL)
265
+
266
+ Move your data between MongoDB and PostgreSQL without writing throwaway scripts. DBDock analyzes the source, proposes a schema mapping, lets you review it, and handles the transfer.
267
+
268
+ ### `dbdock analyze` — Understand your database first
269
+
270
+ ```bash
271
+ npx dbdock analyze "mongodb://localhost:27017/myapp"
272
+ npx dbdock analyze "postgresql://user:pass@localhost:5432/myapp"
273
+ ```
274
+
275
+ Scans the source database and shows you everything — collections/tables, field types, nested structures, inconsistencies (like a `price` field that's a string in 200 docs and a number in 15,000), and missing fields.
276
+
277
+ ```
278
+ DBDock - Database Analysis
279
+ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
280
+
281
+ ℹ Database: MongoDB — myapp
282
+ ℹ Host: localhost:27017
283
+
284
+ ✓ Analysis complete
285
+
286
+ Found 4 collections, 57.2K total documents
287
+
288
+ users (45K docs)
289
+ ├─ _id (objectId)
290
+ ├─ name (string)
291
+ ├─ email (string)
292
+ ├─ address (object)
293
+ │ ├─ street (string)
294
+ │ ├─ city (string)
295
+ │ └─ zip (string)
296
+ ├─ phone (string) [62% present]
297
+ └─ orders (array: object)
298
+
299
+ products (12K docs)
300
+ ├─ _id (objectId)
301
+ ├─ title (string)
302
+ ├─ price (string(203), number(11797)) ⚠ mixed types
303
+ ├─ tags (array: string)
304
+ └─ meta (object)
305
+ ```
306
+
307
+ ---
308
+
309
+ ### `dbdock migrate` — Cross-database migration
310
+
311
+ ```bash
312
+ npx dbdock migrate "mongodb://localhost:27017/myapp" "postgresql://user:pass@localhost:5432/myapp"
313
+ ```
314
+
315
+ DBDock analyzes the source, generates a schema mapping proposal, and presents it for review before touching anything:
316
+
317
+ ```
318
+ DBDock - Cross-Database Migration
319
+ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
320
+
321
+ ℹ Source: MongoDB — myapp
322
+ ℹ Target: PostgreSQL — myapp
323
+
324
+ ✓ Source analyzed: 4 collections, 57.2K documents
325
+
326
+ Proposed Schema Mapping:
327
+
328
+ users → users
329
+ ├─ _id → (uuid_from_objectid) users.id (uuid) PK
330
+ ├─ name → users.name (text)
331
+ ├─ email → users.email (text)
332
+ ├─ address {} → user_addresses (1:1 relation)
333
+ │ ├─ street → street (text)
334
+ │ ├─ city → city (text)
335
+ │ └─ zip → zip (text)
336
+ ├─ orders [] → user_orders child table
337
+
338
+ products → products
339
+ ├─ _id → (uuid_from_objectid) products.id (uuid) PK
340
+ ├─ title → products.title (text)
341
+ ├─ price → products.price (numeric) nullable
342
+ ├─ tags [] → product_tags text[]
343
+ ├─ meta {} → products.meta (jsonb)
344
+
345
+ ⚠ Conflicts Found:
346
+
347
+ • products.price: string in 203 docs, number in 11797 docs
348
+ → Suggestion: cast to numeric, log failures
349
+
350
+ • users.phone: missing in 38.0% of documents
351
+ → Suggestion: nullable column
352
+
353
+ ? Accept mapping? (Y / export / cancel)
354
+ ```
355
+
356
+ You review the mapping, then choose: execute it, export it as a config file to tweak, or cancel.
357
+
358
+ ---
359
+
360
+ ### What it handles
361
+
362
+ | Scenario | How DBDock handles it |
363
+ |---|---|
364
+ | **Nested objects** | Consistent shape → flattened to a related table. Varying/messy → kept as `jsonb` column |
365
+ | **Arrays of primitives** | `tags: ["a", "b"]` → PostgreSQL array column or junction table |
366
+ | **Arrays of objects** | `orders: [{item, qty}]` → child table with foreign key back to parent |
367
+ | **Missing fields** | Detects frequency across all documents, makes sparse fields nullable |
368
+ | **Type mismatches** | Same field with different types → casts to majority type, logs failures to `_migration_errors` |
369
+ | **ObjectId references** | Auto-detects `userId: ObjectId(...)` patterns → creates proper foreign keys |
370
+ | **Deep nesting** | Flattens up to configurable depth (default: 2), stores deeper levels as `jsonb` |
371
+ | **Postgres → Mongo** | 1:1 joins → embedded objects. Small 1:many → embedded arrays. Large 1:many → separate collections with refs |
372
+ | **Many-to-many** | Junction tables → arrays of values in the document |
373
+
374
+ ---
375
+
376
+ ### The reverse — PostgreSQL to MongoDB
377
+
378
+ ```bash
379
+ npx dbdock migrate "postgresql://user:pass@localhost:5432/myapp" "mongodb://localhost:27017/myapp"
380
+ ```
381
+
382
+ DBDock detects table relationships and proposes embedding vs referencing strategies:
383
+
384
+ ```
385
+ Proposed Document Mapping:
386
+
387
+ users → users collection
388
+ ├─ id → _id
389
+ ├─ name → name
390
+ ├─ email → email
391
+ ├─ addresses → embed object as address
392
+ ├─ orders → embed array as orders (< 1000 rows)
393
+
394
+ products → products collection
395
+ ├─ id → _id
396
+ ├─ title → title
397
+ ├─ price → price
398
+ ├─ product_tags → embed as tags array
399
+ ```
400
+
401
+ Small 1:1 and 1:many relations get embedded. Large 1:many relations stay as separate collections with reference fields. You can override per table.
402
+
403
+ ---
404
+
405
+ ### Dry run & validation
406
+
407
+ ```bash
408
+ npx dbdock migrate --dry-run "mongodb://..." "postgresql://..."
409
+ ```
410
+
411
+ Runs the full migration into a temporary schema, validates counts and referential integrity, then cleans up. Nothing touches the real target:
412
+
413
+ ```
414
+ Dry Run Results:
415
+ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
416
+ ✔ users: 45,000 → 45,000
417
+ ✔ addresses: 45,000 → 44,998 (2 failed)
418
+ ✔ orders: 312,400 → 312,400
419
+ ✔ products: 12,000 → 12,000
420
+ ✔ product_tags: 38,200 → 38,200
421
+
422
+ ⚠ 2 rows failed (see _migration_errors)
423
+ ✓ All foreign keys valid — dry run passed
424
+ ```
425
+
426
+ ---
427
+
428
+ ### Incremental / delta migration
429
+
430
+ Already migrated once but your app is still running on the old database? Sync only new or changed data:
431
+
432
+ ```bash
433
+ npx dbdock migrate --incremental --since "2026-03-10" "mongodb://..." "postgresql://..."
434
+ ```
435
+
436
+ Uses `createdAt`/`updatedAt` timestamps to only transfer new and changed documents. Existing rows in the target are upserted.
437
+
438
+ ---
439
+
440
+ ### Save & reuse config
441
+
442
+ Export the mapping for your team to use reproducibly:
443
+
444
+ ```bash
445
+ npx dbdock migrate --export-config ./migration.yaml "mongodb://..." "postgresql://..."
446
+ ```
447
+
448
+ Then anyone runs the same migration:
449
+
450
+ ```bash
451
+ npx dbdock migrate --config ./migration.yaml "mongodb://..." "postgresql://..."
452
+ ```
453
+
454
+ Tweak the YAML/JSON config to adjust type mappings, embedding strategies, or rename target tables — then re-run.
455
+
456
+ ---
457
+
458
+ ### Migration options
459
+
460
+ | Flag | What it does |
461
+ |---|---|
462
+ | `--dry-run` | Migrate into temp schema, validate, clean up |
463
+ | `--incremental` | Only sync new/changed data |
464
+ | `--since <date>` | Cutoff date for incremental mode (ISO format) |
465
+ | `--config <path>` | Load a saved migration config (YAML or JSON) |
466
+ | `--export-config <path>` | Save migration plan to file without executing |
467
+ | `--batch-size <n>` | Documents per batch (default: 1000) |
468
+ | `--max-depth <n>` | Max nesting depth before storing as jsonb (default: 2) |
469
+
470
+ ### Core principles
471
+
472
+ - **Never lose data** — failed rows go to `_migration_errors`, never silently dropped
473
+ - **Never surprise the user** — full mapping shown before execution, conflicts flagged
474
+ - **Always let you review** — nothing executes without explicit confirmation
475
+ - **Reproducible** — export/import configs for team-wide consistency
476
+
477
+ ---
478
+
261
479
  ## Storage Providers
262
480
 
263
481
  Pick your storage during `dbdock init`, or set it in `dbdock.config.json`:
@@ -327,13 +545,20 @@ DBDock splits your config into two parts by design:
327
545
 
328
546
  | What | Where | Git safe? |
329
547
  |------|-------|-----------|
330
- | Host, port, bucket names, settings | `dbdock.config.json` | Yes |
331
- | Passwords, API keys, secrets | `.env` | No (auto-gitignored) |
548
+ | Host, port, bucket names, settings | `dbdock.config.json` or env | Yes (if in config) |
549
+ | Passwords, API keys, secrets | `.env` or `DBDOCK_DB_URL` | No (auto-gitignored) |
332
550
 
333
551
  ### Environment Variables
334
552
 
553
+ Use either a **full database URL** or **separate credentials**:
554
+
335
555
  ```bash
336
- DBDOCK_DB_PASSWORD=your-database-password # Required
556
+ # Option 1: Full URL (env-only config, no password var needed)
557
+ DBDOCK_DB_URL=postgresql://user:password@host:5432/database
558
+ # or DATABASE_URL=postgresql://user:password@host:5432/database
559
+
560
+ # Option 2: Separate credentials (with or without dbdock.config.json)
561
+ DBDOCK_DB_PASSWORD=your-database-password # Required if not using URL
337
562
  DBDOCK_STORAGE_ACCESS_KEY=your-access-key # For cloud storage
338
563
  DBDOCK_STORAGE_SECRET_KEY=your-secret-key # For cloud storage
339
564
  DBDOCK_ENCRYPTION_SECRET=64-char-hex-string # If encryption enabled
@@ -342,7 +567,7 @@ DBDOCK_SMTP_PASS=your-app-password # For email alerts
342
567
  DBDOCK_SLACK_WEBHOOK=https://hooks.slack.com/... # For Slack alerts
343
568
  ```
344
569
 
345
- Reads from both `.env` and `.env.local` (`.env.local` takes priority).
570
+ When `DBDOCK_DB_URL` or `DATABASE_URL` is set, it overrides database settings from `dbdock.config.json`. You can run with **env-only** (no config file) by setting the URL plus storage/encryption/alert vars in `.env`. Reads from both `.env` and `.env.local` (`.env.local` takes priority).
346
571
 
347
572
  ### .pgpass Support
348
573
 
@@ -431,7 +656,7 @@ Don't just use the CLI — drop DBDock into your Node.js app and trigger backups
431
656
  npm install dbdock
432
657
  ```
433
658
 
434
- Make sure `dbdock.config.json` exists (run `npx dbdock init` first).
659
+ Use `dbdock.config.json` (run `npx dbdock init`) or configure entirely via env vars (`DBDOCK_DB_URL` / `DATABASE_URL` plus storage and other env vars).
435
660
 
436
661
  ### Create a Backup
437
662
 
@@ -0,0 +1 @@
1
+ export declare function analyzeCommand(url: string): Promise<void>;
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.analyzeCommand = analyzeCommand;
7
+ const ora_1 = __importDefault(require("ora"));
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const logger_1 = require("../utils/logger");
10
+ const migration_engine_1 = require("../../migration/engines/migration.engine");
11
+ async function analyzeCommand(url) {
12
+ console.log('');
13
+ console.log(chalk_1.default.bold(' DBDock - Database Analysis'));
14
+ console.log(chalk_1.default.gray(' ─'.repeat(30)));
15
+ console.log('');
16
+ let parsed;
17
+ try {
18
+ parsed = (0, migration_engine_1.parseDatabaseUrl)(url);
19
+ }
20
+ catch (error) {
21
+ logger_1.logger.error(error instanceof Error ? error.message : String(error));
22
+ process.exit(1);
23
+ }
24
+ logger_1.logger.info(`Database: ${chalk_1.default.cyan(parsed.type === 'mongodb' ? 'MongoDB' : 'PostgreSQL')} — ${parsed.database}`);
25
+ logger_1.logger.info(`Host: ${parsed.host}:${parsed.port}`);
26
+ console.log('');
27
+ const spinner = (0, ora_1.default)('Analyzing database structure...').start();
28
+ try {
29
+ const analysis = await (0, migration_engine_1.analyzeDatabase)(url);
30
+ spinner.succeed('Analysis complete');
31
+ console.log('');
32
+ if (analysis.type === 'mongodb') {
33
+ displayMongoAnalysis(analysis);
34
+ }
35
+ else {
36
+ displayPostgresAnalysis(analysis);
37
+ }
38
+ }
39
+ catch (error) {
40
+ spinner.fail('Analysis failed');
41
+ logger_1.logger.error(error instanceof Error ? error.message : String(error));
42
+ process.exit(1);
43
+ }
44
+ }
45
+ function displayMongoAnalysis(analysis) {
46
+ console.log(chalk_1.default.bold(` Found ${chalk_1.default.cyan(String(analysis.collections.length))} collections, ${chalk_1.default.cyan(formatNumber(analysis.totalDocuments))} total documents`));
47
+ console.log('');
48
+ for (const collection of analysis.collections) {
49
+ console.log(chalk_1.default.bold(` ${chalk_1.default.green(collection.name)} ${chalk_1.default.gray(`(${formatNumber(collection.documentCount)} docs)`)}`));
50
+ for (let i = 0; i < collection.fields.length; i++) {
51
+ const field = collection.fields[i];
52
+ const isLast = i === collection.fields.length - 1;
53
+ const prefix = isLast ? ' └─' : ' ├─';
54
+ displayMongoField(field, prefix, isLast ? ' ' : ' │ ');
55
+ }
56
+ console.log('');
57
+ }
58
+ }
59
+ function displayMongoField(field, prefix, childPrefix) {
60
+ const typeEntries = Object.entries(field.types).filter(([t]) => t !== 'null' && t !== 'undefined');
61
+ const typeStr = typeEntries
62
+ .map(([t, c]) => {
63
+ if (typeEntries.length > 1)
64
+ return `${t}(${c})`;
65
+ return t;
66
+ })
67
+ .join(', ');
68
+ let extra = '';
69
+ if (field.frequency < 100) {
70
+ extra += chalk_1.default.yellow(` [${field.frequency.toFixed(0)}% present]`);
71
+ }
72
+ if (field.isArray) {
73
+ extra += chalk_1.default.blue(` [array: ${field.arrayElementType || 'mixed'}]`);
74
+ }
75
+ if (field.isObjectId && field.name !== '_id') {
76
+ extra += chalk_1.default.magenta(` → ref${field.possibleReference ? `: ${field.possibleReference}` : ''}`);
77
+ }
78
+ if (typeEntries.length > 1) {
79
+ extra += chalk_1.default.red(' ⚠ mixed types');
80
+ }
81
+ console.log(`${prefix} ${chalk_1.default.white(field.name)} ${chalk_1.default.gray(`(${typeStr})`)}${extra}`);
82
+ if (field.nestedFields && field.isNestedObject && !field.isArray) {
83
+ for (let i = 0; i < field.nestedFields.length; i++) {
84
+ const nested = field.nestedFields[i];
85
+ const isLast = i === field.nestedFields.length - 1;
86
+ const nPrefix = childPrefix + (isLast ? ' └─' : ' ├─');
87
+ const nChildPrefix = childPrefix + (isLast ? ' ' : ' │ ');
88
+ displayMongoField(nested, nPrefix, nChildPrefix);
89
+ }
90
+ }
91
+ }
92
+ function displayPostgresAnalysis(analysis) {
93
+ console.log(chalk_1.default.bold(` Found ${chalk_1.default.cyan(String(analysis.tables.length))} tables, ${chalk_1.default.cyan(formatNumber(analysis.totalRows))} total rows`));
94
+ console.log('');
95
+ for (const table of analysis.tables) {
96
+ console.log(chalk_1.default.bold(` ${chalk_1.default.green(table.name)} ${chalk_1.default.gray(`(${formatNumber(table.rowCount)} rows)`)}`));
97
+ for (let i = 0; i < table.columns.length; i++) {
98
+ const col = table.columns[i];
99
+ const isLast = i === table.columns.length - 1 && table.foreignKeys.length === 0;
100
+ const prefix = isLast ? ' └─' : ' ├─';
101
+ let extra = '';
102
+ if (col.isPrimaryKey)
103
+ extra += chalk_1.default.yellow(' PK');
104
+ if (col.isUnique && !col.isPrimaryKey)
105
+ extra += chalk_1.default.blue(' UNIQUE');
106
+ if (!col.isNullable)
107
+ extra += chalk_1.default.gray(' NOT NULL');
108
+ if (col.columnDefault)
109
+ extra += chalk_1.default.gray(` DEFAULT ${col.columnDefault}`);
110
+ const fk = table.foreignKeys.find((f) => f.columnName === col.name);
111
+ if (fk) {
112
+ extra += chalk_1.default.magenta(` → ${fk.referencedTable}.${fk.referencedColumn}`);
113
+ }
114
+ console.log(`${prefix} ${chalk_1.default.white(col.name)} ${chalk_1.default.gray(`(${col.dataType})`)}${extra}`);
115
+ }
116
+ if (table.indexes.length > 0) {
117
+ const nonPkIndexes = table.indexes.filter((idx) => !idx.isPrimary);
118
+ for (let i = 0; i < nonPkIndexes.length; i++) {
119
+ const idx = nonPkIndexes[i];
120
+ const isLast = i === nonPkIndexes.length - 1;
121
+ const prefix = isLast ? ' └─' : ' ├─';
122
+ console.log(`${prefix} ${chalk_1.default.gray('idx:')} ${idx.name} ${chalk_1.default.gray(`(${idx.columns.join(', ')})`)}${idx.isUnique ? chalk_1.default.blue(' UNIQUE') : ''}`);
123
+ }
124
+ }
125
+ console.log('');
126
+ }
127
+ }
128
+ function formatNumber(n) {
129
+ if (n >= 1000000)
130
+ return `${(n / 1000000).toFixed(1)}M`;
131
+ if (n >= 1000)
132
+ return `${(n / 1000).toFixed(1)}K`;
133
+ return String(n);
134
+ }
135
+ //# sourceMappingURL=analyze.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../../src/cli/commands/analyze.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ interface MigrateOptions {
2
+ dryRun?: boolean;
3
+ incremental?: boolean;
4
+ since?: string;
5
+ config?: string;
6
+ exportConfig?: string;
7
+ batchSize?: number;
8
+ maxDepth?: number;
9
+ }
10
+ export declare function crossMigrateCommand(sourceUrl: string, targetUrl: string, options: MigrateOptions): Promise<void>;
11
+ export {};