@hasna/cloud 0.1.11 → 0.1.12
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/dist/cli/index.js +109 -95
- package/dist/index.js +109 -95
- package/dist/mcp/index.js +109 -95
- package/dist/sync.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -11452,60 +11452,100 @@ async function syncTransfer(source, target, options, _direction) {
|
|
|
11452
11452
|
primaryKey: pkOption
|
|
11453
11453
|
} = options;
|
|
11454
11454
|
const results = [];
|
|
11455
|
-
|
|
11455
|
+
const sqliteTarget = !isAsyncAdapter(target) ? target : null;
|
|
11456
|
+
if (sqliteTarget) {
|
|
11456
11457
|
try {
|
|
11457
|
-
|
|
11458
|
+
sqliteTarget.exec("PRAGMA foreign_keys = OFF");
|
|
11458
11459
|
} catch {}
|
|
11459
11460
|
}
|
|
11460
|
-
|
|
11461
|
-
|
|
11462
|
-
|
|
11463
|
-
|
|
11464
|
-
rowsRead: 0,
|
|
11465
|
-
rowsWritten: 0,
|
|
11466
|
-
rowsSkipped: 0,
|
|
11467
|
-
errors: []
|
|
11468
|
-
};
|
|
11469
|
-
try {
|
|
11470
|
-
onProgress?.({
|
|
11461
|
+
try {
|
|
11462
|
+
for (let i = 0;i < tables.length; i++) {
|
|
11463
|
+
const table = tables[i];
|
|
11464
|
+
const result = {
|
|
11471
11465
|
table,
|
|
11472
|
-
phase: "reading",
|
|
11473
11466
|
rowsRead: 0,
|
|
11474
11467
|
rowsWritten: 0,
|
|
11475
|
-
|
|
11476
|
-
|
|
11477
|
-
}
|
|
11478
|
-
|
|
11479
|
-
result.rowsRead = rows.length;
|
|
11480
|
-
if (rows.length === 0) {
|
|
11468
|
+
rowsSkipped: 0,
|
|
11469
|
+
errors: []
|
|
11470
|
+
};
|
|
11471
|
+
try {
|
|
11481
11472
|
onProgress?.({
|
|
11482
11473
|
table,
|
|
11483
|
-
phase: "
|
|
11474
|
+
phase: "reading",
|
|
11484
11475
|
rowsRead: 0,
|
|
11485
11476
|
rowsWritten: 0,
|
|
11486
11477
|
totalTables: tables.length,
|
|
11487
11478
|
currentTableIndex: i
|
|
11488
11479
|
});
|
|
11489
|
-
|
|
11490
|
-
|
|
11491
|
-
|
|
11492
|
-
|
|
11493
|
-
|
|
11494
|
-
|
|
11495
|
-
|
|
11496
|
-
|
|
11497
|
-
|
|
11498
|
-
|
|
11499
|
-
|
|
11500
|
-
|
|
11501
|
-
|
|
11502
|
-
|
|
11503
|
-
|
|
11504
|
-
|
|
11505
|
-
|
|
11506
|
-
|
|
11507
|
-
|
|
11508
|
-
|
|
11480
|
+
const rows = await readAll(source, `SELECT * FROM "${table}"`);
|
|
11481
|
+
result.rowsRead = rows.length;
|
|
11482
|
+
if (rows.length === 0) {
|
|
11483
|
+
onProgress?.({
|
|
11484
|
+
table,
|
|
11485
|
+
phase: "done",
|
|
11486
|
+
rowsRead: 0,
|
|
11487
|
+
rowsWritten: 0,
|
|
11488
|
+
totalTables: tables.length,
|
|
11489
|
+
currentTableIndex: i
|
|
11490
|
+
});
|
|
11491
|
+
results.push(result);
|
|
11492
|
+
continue;
|
|
11493
|
+
}
|
|
11494
|
+
const pkColumns = await resolvePrimaryKeys(source, target, table, pkOption);
|
|
11495
|
+
const sourceColumns = Object.keys(rows[0]);
|
|
11496
|
+
let targetColumns = null;
|
|
11497
|
+
if (!isAsyncAdapter(target)) {
|
|
11498
|
+
try {
|
|
11499
|
+
const colInfo = target.all(`PRAGMA table_info("${table}")`);
|
|
11500
|
+
targetColumns = new Set(colInfo.map((c) => c.name));
|
|
11501
|
+
} catch {}
|
|
11502
|
+
} else {
|
|
11503
|
+
try {
|
|
11504
|
+
const colInfo = await target.all(`SELECT column_name FROM information_schema.columns WHERE table_schema = 'public' AND table_name = '${table}'`);
|
|
11505
|
+
targetColumns = new Set(colInfo.map((c) => c.column_name));
|
|
11506
|
+
} catch {}
|
|
11507
|
+
}
|
|
11508
|
+
const columns = targetColumns ? sourceColumns.filter((c) => targetColumns.has(c)) : sourceColumns;
|
|
11509
|
+
if (pkColumns.length === 0) {
|
|
11510
|
+
result.errors.push(`Table "${table}" has no primary key — inserting without conflict handling`);
|
|
11511
|
+
onProgress?.({
|
|
11512
|
+
table,
|
|
11513
|
+
phase: "writing",
|
|
11514
|
+
rowsRead: result.rowsRead,
|
|
11515
|
+
rowsWritten: 0,
|
|
11516
|
+
totalTables: tables.length,
|
|
11517
|
+
currentTableIndex: i
|
|
11518
|
+
});
|
|
11519
|
+
for (let offset = 0;offset < rows.length; offset += batchSize) {
|
|
11520
|
+
const batch = rows.slice(offset, offset + batchSize);
|
|
11521
|
+
try {
|
|
11522
|
+
if (isAsyncAdapter(target)) {
|
|
11523
|
+
await batchInsertPg(target, table, columns, batch);
|
|
11524
|
+
} else {
|
|
11525
|
+
batchInsertSqlite(target, table, columns, batch);
|
|
11526
|
+
}
|
|
11527
|
+
result.rowsWritten += batch.length;
|
|
11528
|
+
} catch (err) {
|
|
11529
|
+
result.errors.push(`Batch at offset ${offset}: ${err?.message ?? String(err)}`);
|
|
11530
|
+
}
|
|
11531
|
+
}
|
|
11532
|
+
onProgress?.({
|
|
11533
|
+
table,
|
|
11534
|
+
phase: "done",
|
|
11535
|
+
rowsRead: result.rowsRead,
|
|
11536
|
+
rowsWritten: result.rowsWritten,
|
|
11537
|
+
totalTables: tables.length,
|
|
11538
|
+
currentTableIndex: i
|
|
11539
|
+
});
|
|
11540
|
+
results.push(result);
|
|
11541
|
+
continue;
|
|
11542
|
+
}
|
|
11543
|
+
const missingPks = pkColumns.filter((pk) => !columns.includes(pk));
|
|
11544
|
+
if (missingPks.length > 0) {
|
|
11545
|
+
result.errors.push(`Table "${table}" missing PK columns in data: ${missingPks.join(", ")} — skipping`);
|
|
11546
|
+
results.push(result);
|
|
11547
|
+
continue;
|
|
11548
|
+
}
|
|
11509
11549
|
onProgress?.({
|
|
11510
11550
|
table,
|
|
11511
11551
|
phase: "writing",
|
|
@@ -11514,18 +11554,27 @@ async function syncTransfer(source, target, options, _direction) {
|
|
|
11514
11554
|
totalTables: tables.length,
|
|
11515
11555
|
currentTableIndex: i
|
|
11516
11556
|
});
|
|
11557
|
+
const updateCols = columns.filter((c) => !pkColumns.includes(c));
|
|
11517
11558
|
for (let offset = 0;offset < rows.length; offset += batchSize) {
|
|
11518
11559
|
const batch = rows.slice(offset, offset + batchSize);
|
|
11519
11560
|
try {
|
|
11520
11561
|
if (isAsyncAdapter(target)) {
|
|
11521
|
-
await
|
|
11562
|
+
await batchUpsertPg(target, table, columns, updateCols, pkColumns, batch);
|
|
11522
11563
|
} else {
|
|
11523
|
-
|
|
11564
|
+
batchUpsertSqlite(target, table, columns, updateCols, pkColumns, batch);
|
|
11524
11565
|
}
|
|
11525
11566
|
result.rowsWritten += batch.length;
|
|
11526
11567
|
} catch (err) {
|
|
11527
11568
|
result.errors.push(`Batch at offset ${offset}: ${err?.message ?? String(err)}`);
|
|
11528
11569
|
}
|
|
11570
|
+
onProgress?.({
|
|
11571
|
+
table,
|
|
11572
|
+
phase: "writing",
|
|
11573
|
+
rowsRead: result.rowsRead,
|
|
11574
|
+
rowsWritten: result.rowsWritten,
|
|
11575
|
+
totalTables: tables.length,
|
|
11576
|
+
currentTableIndex: i
|
|
11577
|
+
});
|
|
11529
11578
|
}
|
|
11530
11579
|
onProgress?.({
|
|
11531
11580
|
table,
|
|
@@ -11535,62 +11584,27 @@ async function syncTransfer(source, target, options, _direction) {
|
|
|
11535
11584
|
totalTables: tables.length,
|
|
11536
11585
|
currentTableIndex: i
|
|
11537
11586
|
});
|
|
11538
|
-
|
|
11539
|
-
|
|
11540
|
-
}
|
|
11541
|
-
const missingPks = pkColumns.filter((pk) => !columns.includes(pk));
|
|
11542
|
-
if (missingPks.length > 0) {
|
|
11543
|
-
result.errors.push(`Table "${table}" missing PK columns in data: ${missingPks.join(", ")} — skipping`);
|
|
11544
|
-
results.push(result);
|
|
11545
|
-
continue;
|
|
11587
|
+
} catch (err) {
|
|
11588
|
+
result.errors.push(`Table "${table}": ${err?.message ?? String(err)}`);
|
|
11546
11589
|
}
|
|
11547
|
-
|
|
11548
|
-
|
|
11549
|
-
|
|
11550
|
-
|
|
11551
|
-
|
|
11552
|
-
|
|
11553
|
-
|
|
11554
|
-
|
|
11555
|
-
|
|
11556
|
-
|
|
11557
|
-
|
|
11558
|
-
|
|
11559
|
-
if (
|
|
11560
|
-
|
|
11561
|
-
} else {
|
|
11562
|
-
batchUpsertSqlite(target, table, columns, updateCols, pkColumns, batch);
|
|
11590
|
+
results.push(result);
|
|
11591
|
+
}
|
|
11592
|
+
} finally {
|
|
11593
|
+
if (sqliteTarget) {
|
|
11594
|
+
try {
|
|
11595
|
+
sqliteTarget.exec("PRAGMA foreign_keys = ON");
|
|
11596
|
+
} catch {}
|
|
11597
|
+
try {
|
|
11598
|
+
const violations = sqliteTarget.all("PRAGMA foreign_key_check");
|
|
11599
|
+
if (violations.length > 0) {
|
|
11600
|
+
const tables2 = [...new Set(violations.map((v) => v.table))];
|
|
11601
|
+
const msg = `FK integrity check: ${violations.length} violation(s) in table(s): ${tables2.join(", ")}`;
|
|
11602
|
+
if (results.length > 0) {
|
|
11603
|
+
results[results.length - 1].errors.push(msg);
|
|
11563
11604
|
}
|
|
11564
|
-
result.rowsWritten += batch.length;
|
|
11565
|
-
} catch (err) {
|
|
11566
|
-
result.errors.push(`Batch at offset ${offset}: ${err?.message ?? String(err)}`);
|
|
11567
11605
|
}
|
|
11568
|
-
|
|
11569
|
-
table,
|
|
11570
|
-
phase: "writing",
|
|
11571
|
-
rowsRead: result.rowsRead,
|
|
11572
|
-
rowsWritten: result.rowsWritten,
|
|
11573
|
-
totalTables: tables.length,
|
|
11574
|
-
currentTableIndex: i
|
|
11575
|
-
});
|
|
11576
|
-
}
|
|
11577
|
-
onProgress?.({
|
|
11578
|
-
table,
|
|
11579
|
-
phase: "done",
|
|
11580
|
-
rowsRead: result.rowsRead,
|
|
11581
|
-
rowsWritten: result.rowsWritten,
|
|
11582
|
-
totalTables: tables.length,
|
|
11583
|
-
currentTableIndex: i
|
|
11584
|
-
});
|
|
11585
|
-
} catch (err) {
|
|
11586
|
-
result.errors.push(`Table "${table}": ${err?.message ?? String(err)}`);
|
|
11606
|
+
} catch {}
|
|
11587
11607
|
}
|
|
11588
|
-
results.push(result);
|
|
11589
|
-
}
|
|
11590
|
-
if (!isAsyncAdapter(target)) {
|
|
11591
|
-
try {
|
|
11592
|
-
target.run("PRAGMA foreign_keys = ON");
|
|
11593
|
-
} catch {}
|
|
11594
11608
|
}
|
|
11595
11609
|
return results;
|
|
11596
11610
|
}
|
package/dist/index.js
CHANGED
|
@@ -9444,60 +9444,100 @@ async function syncTransfer(source, target, options, _direction) {
|
|
|
9444
9444
|
primaryKey: pkOption
|
|
9445
9445
|
} = options;
|
|
9446
9446
|
const results = [];
|
|
9447
|
-
|
|
9447
|
+
const sqliteTarget = !isAsyncAdapter(target) ? target : null;
|
|
9448
|
+
if (sqliteTarget) {
|
|
9448
9449
|
try {
|
|
9449
|
-
|
|
9450
|
+
sqliteTarget.exec("PRAGMA foreign_keys = OFF");
|
|
9450
9451
|
} catch {}
|
|
9451
9452
|
}
|
|
9452
|
-
|
|
9453
|
-
|
|
9454
|
-
|
|
9455
|
-
|
|
9456
|
-
rowsRead: 0,
|
|
9457
|
-
rowsWritten: 0,
|
|
9458
|
-
rowsSkipped: 0,
|
|
9459
|
-
errors: []
|
|
9460
|
-
};
|
|
9461
|
-
try {
|
|
9462
|
-
onProgress?.({
|
|
9453
|
+
try {
|
|
9454
|
+
for (let i = 0;i < tables.length; i++) {
|
|
9455
|
+
const table = tables[i];
|
|
9456
|
+
const result = {
|
|
9463
9457
|
table,
|
|
9464
|
-
phase: "reading",
|
|
9465
9458
|
rowsRead: 0,
|
|
9466
9459
|
rowsWritten: 0,
|
|
9467
|
-
|
|
9468
|
-
|
|
9469
|
-
}
|
|
9470
|
-
|
|
9471
|
-
result.rowsRead = rows.length;
|
|
9472
|
-
if (rows.length === 0) {
|
|
9460
|
+
rowsSkipped: 0,
|
|
9461
|
+
errors: []
|
|
9462
|
+
};
|
|
9463
|
+
try {
|
|
9473
9464
|
onProgress?.({
|
|
9474
9465
|
table,
|
|
9475
|
-
phase: "
|
|
9466
|
+
phase: "reading",
|
|
9476
9467
|
rowsRead: 0,
|
|
9477
9468
|
rowsWritten: 0,
|
|
9478
9469
|
totalTables: tables.length,
|
|
9479
9470
|
currentTableIndex: i
|
|
9480
9471
|
});
|
|
9481
|
-
|
|
9482
|
-
|
|
9483
|
-
|
|
9484
|
-
|
|
9485
|
-
|
|
9486
|
-
|
|
9487
|
-
|
|
9488
|
-
|
|
9489
|
-
|
|
9490
|
-
|
|
9491
|
-
|
|
9492
|
-
|
|
9493
|
-
|
|
9494
|
-
|
|
9495
|
-
|
|
9496
|
-
|
|
9497
|
-
|
|
9498
|
-
|
|
9499
|
-
|
|
9500
|
-
|
|
9472
|
+
const rows = await readAll(source, `SELECT * FROM "${table}"`);
|
|
9473
|
+
result.rowsRead = rows.length;
|
|
9474
|
+
if (rows.length === 0) {
|
|
9475
|
+
onProgress?.({
|
|
9476
|
+
table,
|
|
9477
|
+
phase: "done",
|
|
9478
|
+
rowsRead: 0,
|
|
9479
|
+
rowsWritten: 0,
|
|
9480
|
+
totalTables: tables.length,
|
|
9481
|
+
currentTableIndex: i
|
|
9482
|
+
});
|
|
9483
|
+
results.push(result);
|
|
9484
|
+
continue;
|
|
9485
|
+
}
|
|
9486
|
+
const pkColumns = await resolvePrimaryKeys(source, target, table, pkOption);
|
|
9487
|
+
const sourceColumns = Object.keys(rows[0]);
|
|
9488
|
+
let targetColumns = null;
|
|
9489
|
+
if (!isAsyncAdapter(target)) {
|
|
9490
|
+
try {
|
|
9491
|
+
const colInfo = target.all(`PRAGMA table_info("${table}")`);
|
|
9492
|
+
targetColumns = new Set(colInfo.map((c) => c.name));
|
|
9493
|
+
} catch {}
|
|
9494
|
+
} else {
|
|
9495
|
+
try {
|
|
9496
|
+
const colInfo = await target.all(`SELECT column_name FROM information_schema.columns WHERE table_schema = 'public' AND table_name = '${table}'`);
|
|
9497
|
+
targetColumns = new Set(colInfo.map((c) => c.column_name));
|
|
9498
|
+
} catch {}
|
|
9499
|
+
}
|
|
9500
|
+
const columns = targetColumns ? sourceColumns.filter((c) => targetColumns.has(c)) : sourceColumns;
|
|
9501
|
+
if (pkColumns.length === 0) {
|
|
9502
|
+
result.errors.push(`Table "${table}" has no primary key — inserting without conflict handling`);
|
|
9503
|
+
onProgress?.({
|
|
9504
|
+
table,
|
|
9505
|
+
phase: "writing",
|
|
9506
|
+
rowsRead: result.rowsRead,
|
|
9507
|
+
rowsWritten: 0,
|
|
9508
|
+
totalTables: tables.length,
|
|
9509
|
+
currentTableIndex: i
|
|
9510
|
+
});
|
|
9511
|
+
for (let offset = 0;offset < rows.length; offset += batchSize) {
|
|
9512
|
+
const batch = rows.slice(offset, offset + batchSize);
|
|
9513
|
+
try {
|
|
9514
|
+
if (isAsyncAdapter(target)) {
|
|
9515
|
+
await batchInsertPg(target, table, columns, batch);
|
|
9516
|
+
} else {
|
|
9517
|
+
batchInsertSqlite(target, table, columns, batch);
|
|
9518
|
+
}
|
|
9519
|
+
result.rowsWritten += batch.length;
|
|
9520
|
+
} catch (err) {
|
|
9521
|
+
result.errors.push(`Batch at offset ${offset}: ${err?.message ?? String(err)}`);
|
|
9522
|
+
}
|
|
9523
|
+
}
|
|
9524
|
+
onProgress?.({
|
|
9525
|
+
table,
|
|
9526
|
+
phase: "done",
|
|
9527
|
+
rowsRead: result.rowsRead,
|
|
9528
|
+
rowsWritten: result.rowsWritten,
|
|
9529
|
+
totalTables: tables.length,
|
|
9530
|
+
currentTableIndex: i
|
|
9531
|
+
});
|
|
9532
|
+
results.push(result);
|
|
9533
|
+
continue;
|
|
9534
|
+
}
|
|
9535
|
+
const missingPks = pkColumns.filter((pk) => !columns.includes(pk));
|
|
9536
|
+
if (missingPks.length > 0) {
|
|
9537
|
+
result.errors.push(`Table "${table}" missing PK columns in data: ${missingPks.join(", ")} — skipping`);
|
|
9538
|
+
results.push(result);
|
|
9539
|
+
continue;
|
|
9540
|
+
}
|
|
9501
9541
|
onProgress?.({
|
|
9502
9542
|
table,
|
|
9503
9543
|
phase: "writing",
|
|
@@ -9506,18 +9546,27 @@ async function syncTransfer(source, target, options, _direction) {
|
|
|
9506
9546
|
totalTables: tables.length,
|
|
9507
9547
|
currentTableIndex: i
|
|
9508
9548
|
});
|
|
9549
|
+
const updateCols = columns.filter((c) => !pkColumns.includes(c));
|
|
9509
9550
|
for (let offset = 0;offset < rows.length; offset += batchSize) {
|
|
9510
9551
|
const batch = rows.slice(offset, offset + batchSize);
|
|
9511
9552
|
try {
|
|
9512
9553
|
if (isAsyncAdapter(target)) {
|
|
9513
|
-
await
|
|
9554
|
+
await batchUpsertPg(target, table, columns, updateCols, pkColumns, batch);
|
|
9514
9555
|
} else {
|
|
9515
|
-
|
|
9556
|
+
batchUpsertSqlite(target, table, columns, updateCols, pkColumns, batch);
|
|
9516
9557
|
}
|
|
9517
9558
|
result.rowsWritten += batch.length;
|
|
9518
9559
|
} catch (err) {
|
|
9519
9560
|
result.errors.push(`Batch at offset ${offset}: ${err?.message ?? String(err)}`);
|
|
9520
9561
|
}
|
|
9562
|
+
onProgress?.({
|
|
9563
|
+
table,
|
|
9564
|
+
phase: "writing",
|
|
9565
|
+
rowsRead: result.rowsRead,
|
|
9566
|
+
rowsWritten: result.rowsWritten,
|
|
9567
|
+
totalTables: tables.length,
|
|
9568
|
+
currentTableIndex: i
|
|
9569
|
+
});
|
|
9521
9570
|
}
|
|
9522
9571
|
onProgress?.({
|
|
9523
9572
|
table,
|
|
@@ -9527,62 +9576,27 @@ async function syncTransfer(source, target, options, _direction) {
|
|
|
9527
9576
|
totalTables: tables.length,
|
|
9528
9577
|
currentTableIndex: i
|
|
9529
9578
|
});
|
|
9530
|
-
|
|
9531
|
-
|
|
9532
|
-
}
|
|
9533
|
-
const missingPks = pkColumns.filter((pk) => !columns.includes(pk));
|
|
9534
|
-
if (missingPks.length > 0) {
|
|
9535
|
-
result.errors.push(`Table "${table}" missing PK columns in data: ${missingPks.join(", ")} — skipping`);
|
|
9536
|
-
results.push(result);
|
|
9537
|
-
continue;
|
|
9579
|
+
} catch (err) {
|
|
9580
|
+
result.errors.push(`Table "${table}": ${err?.message ?? String(err)}`);
|
|
9538
9581
|
}
|
|
9539
|
-
|
|
9540
|
-
|
|
9541
|
-
|
|
9542
|
-
|
|
9543
|
-
|
|
9544
|
-
|
|
9545
|
-
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
|
|
9550
|
-
|
|
9551
|
-
if (
|
|
9552
|
-
|
|
9553
|
-
} else {
|
|
9554
|
-
batchUpsertSqlite(target, table, columns, updateCols, pkColumns, batch);
|
|
9582
|
+
results.push(result);
|
|
9583
|
+
}
|
|
9584
|
+
} finally {
|
|
9585
|
+
if (sqliteTarget) {
|
|
9586
|
+
try {
|
|
9587
|
+
sqliteTarget.exec("PRAGMA foreign_keys = ON");
|
|
9588
|
+
} catch {}
|
|
9589
|
+
try {
|
|
9590
|
+
const violations = sqliteTarget.all("PRAGMA foreign_key_check");
|
|
9591
|
+
if (violations.length > 0) {
|
|
9592
|
+
const tables2 = [...new Set(violations.map((v) => v.table))];
|
|
9593
|
+
const msg = `FK integrity check: ${violations.length} violation(s) in table(s): ${tables2.join(", ")}`;
|
|
9594
|
+
if (results.length > 0) {
|
|
9595
|
+
results[results.length - 1].errors.push(msg);
|
|
9555
9596
|
}
|
|
9556
|
-
result.rowsWritten += batch.length;
|
|
9557
|
-
} catch (err) {
|
|
9558
|
-
result.errors.push(`Batch at offset ${offset}: ${err?.message ?? String(err)}`);
|
|
9559
9597
|
}
|
|
9560
|
-
|
|
9561
|
-
table,
|
|
9562
|
-
phase: "writing",
|
|
9563
|
-
rowsRead: result.rowsRead,
|
|
9564
|
-
rowsWritten: result.rowsWritten,
|
|
9565
|
-
totalTables: tables.length,
|
|
9566
|
-
currentTableIndex: i
|
|
9567
|
-
});
|
|
9568
|
-
}
|
|
9569
|
-
onProgress?.({
|
|
9570
|
-
table,
|
|
9571
|
-
phase: "done",
|
|
9572
|
-
rowsRead: result.rowsRead,
|
|
9573
|
-
rowsWritten: result.rowsWritten,
|
|
9574
|
-
totalTables: tables.length,
|
|
9575
|
-
currentTableIndex: i
|
|
9576
|
-
});
|
|
9577
|
-
} catch (err) {
|
|
9578
|
-
result.errors.push(`Table "${table}": ${err?.message ?? String(err)}`);
|
|
9598
|
+
} catch {}
|
|
9579
9599
|
}
|
|
9580
|
-
results.push(result);
|
|
9581
|
-
}
|
|
9582
|
-
if (!isAsyncAdapter(target)) {
|
|
9583
|
-
try {
|
|
9584
|
-
target.run("PRAGMA foreign_keys = ON");
|
|
9585
|
-
} catch {}
|
|
9586
9600
|
}
|
|
9587
9601
|
return results;
|
|
9588
9602
|
}
|
package/dist/mcp/index.js
CHANGED
|
@@ -24791,60 +24791,100 @@ async function syncTransfer(source, target, options, _direction) {
|
|
|
24791
24791
|
primaryKey: pkOption
|
|
24792
24792
|
} = options;
|
|
24793
24793
|
const results = [];
|
|
24794
|
-
|
|
24794
|
+
const sqliteTarget = !isAsyncAdapter(target) ? target : null;
|
|
24795
|
+
if (sqliteTarget) {
|
|
24795
24796
|
try {
|
|
24796
|
-
|
|
24797
|
+
sqliteTarget.exec("PRAGMA foreign_keys = OFF");
|
|
24797
24798
|
} catch {}
|
|
24798
24799
|
}
|
|
24799
|
-
|
|
24800
|
-
|
|
24801
|
-
|
|
24802
|
-
|
|
24803
|
-
rowsRead: 0,
|
|
24804
|
-
rowsWritten: 0,
|
|
24805
|
-
rowsSkipped: 0,
|
|
24806
|
-
errors: []
|
|
24807
|
-
};
|
|
24808
|
-
try {
|
|
24809
|
-
onProgress?.({
|
|
24800
|
+
try {
|
|
24801
|
+
for (let i = 0;i < tables.length; i++) {
|
|
24802
|
+
const table = tables[i];
|
|
24803
|
+
const result = {
|
|
24810
24804
|
table,
|
|
24811
|
-
phase: "reading",
|
|
24812
24805
|
rowsRead: 0,
|
|
24813
24806
|
rowsWritten: 0,
|
|
24814
|
-
|
|
24815
|
-
|
|
24816
|
-
}
|
|
24817
|
-
|
|
24818
|
-
result.rowsRead = rows.length;
|
|
24819
|
-
if (rows.length === 0) {
|
|
24807
|
+
rowsSkipped: 0,
|
|
24808
|
+
errors: []
|
|
24809
|
+
};
|
|
24810
|
+
try {
|
|
24820
24811
|
onProgress?.({
|
|
24821
24812
|
table,
|
|
24822
|
-
phase: "
|
|
24813
|
+
phase: "reading",
|
|
24823
24814
|
rowsRead: 0,
|
|
24824
24815
|
rowsWritten: 0,
|
|
24825
24816
|
totalTables: tables.length,
|
|
24826
24817
|
currentTableIndex: i
|
|
24827
24818
|
});
|
|
24828
|
-
|
|
24829
|
-
|
|
24830
|
-
|
|
24831
|
-
|
|
24832
|
-
|
|
24833
|
-
|
|
24834
|
-
|
|
24835
|
-
|
|
24836
|
-
|
|
24837
|
-
|
|
24838
|
-
|
|
24839
|
-
|
|
24840
|
-
|
|
24841
|
-
|
|
24842
|
-
|
|
24843
|
-
|
|
24844
|
-
|
|
24845
|
-
|
|
24846
|
-
|
|
24847
|
-
|
|
24819
|
+
const rows = await readAll(source, `SELECT * FROM "${table}"`);
|
|
24820
|
+
result.rowsRead = rows.length;
|
|
24821
|
+
if (rows.length === 0) {
|
|
24822
|
+
onProgress?.({
|
|
24823
|
+
table,
|
|
24824
|
+
phase: "done",
|
|
24825
|
+
rowsRead: 0,
|
|
24826
|
+
rowsWritten: 0,
|
|
24827
|
+
totalTables: tables.length,
|
|
24828
|
+
currentTableIndex: i
|
|
24829
|
+
});
|
|
24830
|
+
results.push(result);
|
|
24831
|
+
continue;
|
|
24832
|
+
}
|
|
24833
|
+
const pkColumns = await resolvePrimaryKeys(source, target, table, pkOption);
|
|
24834
|
+
const sourceColumns = Object.keys(rows[0]);
|
|
24835
|
+
let targetColumns = null;
|
|
24836
|
+
if (!isAsyncAdapter(target)) {
|
|
24837
|
+
try {
|
|
24838
|
+
const colInfo = target.all(`PRAGMA table_info("${table}")`);
|
|
24839
|
+
targetColumns = new Set(colInfo.map((c) => c.name));
|
|
24840
|
+
} catch {}
|
|
24841
|
+
} else {
|
|
24842
|
+
try {
|
|
24843
|
+
const colInfo = await target.all(`SELECT column_name FROM information_schema.columns WHERE table_schema = 'public' AND table_name = '${table}'`);
|
|
24844
|
+
targetColumns = new Set(colInfo.map((c) => c.column_name));
|
|
24845
|
+
} catch {}
|
|
24846
|
+
}
|
|
24847
|
+
const columns = targetColumns ? sourceColumns.filter((c) => targetColumns.has(c)) : sourceColumns;
|
|
24848
|
+
if (pkColumns.length === 0) {
|
|
24849
|
+
result.errors.push(`Table "${table}" has no primary key — inserting without conflict handling`);
|
|
24850
|
+
onProgress?.({
|
|
24851
|
+
table,
|
|
24852
|
+
phase: "writing",
|
|
24853
|
+
rowsRead: result.rowsRead,
|
|
24854
|
+
rowsWritten: 0,
|
|
24855
|
+
totalTables: tables.length,
|
|
24856
|
+
currentTableIndex: i
|
|
24857
|
+
});
|
|
24858
|
+
for (let offset = 0;offset < rows.length; offset += batchSize) {
|
|
24859
|
+
const batch = rows.slice(offset, offset + batchSize);
|
|
24860
|
+
try {
|
|
24861
|
+
if (isAsyncAdapter(target)) {
|
|
24862
|
+
await batchInsertPg(target, table, columns, batch);
|
|
24863
|
+
} else {
|
|
24864
|
+
batchInsertSqlite(target, table, columns, batch);
|
|
24865
|
+
}
|
|
24866
|
+
result.rowsWritten += batch.length;
|
|
24867
|
+
} catch (err) {
|
|
24868
|
+
result.errors.push(`Batch at offset ${offset}: ${err?.message ?? String(err)}`);
|
|
24869
|
+
}
|
|
24870
|
+
}
|
|
24871
|
+
onProgress?.({
|
|
24872
|
+
table,
|
|
24873
|
+
phase: "done",
|
|
24874
|
+
rowsRead: result.rowsRead,
|
|
24875
|
+
rowsWritten: result.rowsWritten,
|
|
24876
|
+
totalTables: tables.length,
|
|
24877
|
+
currentTableIndex: i
|
|
24878
|
+
});
|
|
24879
|
+
results.push(result);
|
|
24880
|
+
continue;
|
|
24881
|
+
}
|
|
24882
|
+
const missingPks = pkColumns.filter((pk) => !columns.includes(pk));
|
|
24883
|
+
if (missingPks.length > 0) {
|
|
24884
|
+
result.errors.push(`Table "${table}" missing PK columns in data: ${missingPks.join(", ")} — skipping`);
|
|
24885
|
+
results.push(result);
|
|
24886
|
+
continue;
|
|
24887
|
+
}
|
|
24848
24888
|
onProgress?.({
|
|
24849
24889
|
table,
|
|
24850
24890
|
phase: "writing",
|
|
@@ -24853,18 +24893,27 @@ async function syncTransfer(source, target, options, _direction) {
|
|
|
24853
24893
|
totalTables: tables.length,
|
|
24854
24894
|
currentTableIndex: i
|
|
24855
24895
|
});
|
|
24896
|
+
const updateCols = columns.filter((c) => !pkColumns.includes(c));
|
|
24856
24897
|
for (let offset = 0;offset < rows.length; offset += batchSize) {
|
|
24857
24898
|
const batch = rows.slice(offset, offset + batchSize);
|
|
24858
24899
|
try {
|
|
24859
24900
|
if (isAsyncAdapter(target)) {
|
|
24860
|
-
await
|
|
24901
|
+
await batchUpsertPg(target, table, columns, updateCols, pkColumns, batch);
|
|
24861
24902
|
} else {
|
|
24862
|
-
|
|
24903
|
+
batchUpsertSqlite(target, table, columns, updateCols, pkColumns, batch);
|
|
24863
24904
|
}
|
|
24864
24905
|
result.rowsWritten += batch.length;
|
|
24865
24906
|
} catch (err) {
|
|
24866
24907
|
result.errors.push(`Batch at offset ${offset}: ${err?.message ?? String(err)}`);
|
|
24867
24908
|
}
|
|
24909
|
+
onProgress?.({
|
|
24910
|
+
table,
|
|
24911
|
+
phase: "writing",
|
|
24912
|
+
rowsRead: result.rowsRead,
|
|
24913
|
+
rowsWritten: result.rowsWritten,
|
|
24914
|
+
totalTables: tables.length,
|
|
24915
|
+
currentTableIndex: i
|
|
24916
|
+
});
|
|
24868
24917
|
}
|
|
24869
24918
|
onProgress?.({
|
|
24870
24919
|
table,
|
|
@@ -24874,62 +24923,27 @@ async function syncTransfer(source, target, options, _direction) {
|
|
|
24874
24923
|
totalTables: tables.length,
|
|
24875
24924
|
currentTableIndex: i
|
|
24876
24925
|
});
|
|
24877
|
-
|
|
24878
|
-
|
|
24879
|
-
}
|
|
24880
|
-
const missingPks = pkColumns.filter((pk) => !columns.includes(pk));
|
|
24881
|
-
if (missingPks.length > 0) {
|
|
24882
|
-
result.errors.push(`Table "${table}" missing PK columns in data: ${missingPks.join(", ")} — skipping`);
|
|
24883
|
-
results.push(result);
|
|
24884
|
-
continue;
|
|
24926
|
+
} catch (err) {
|
|
24927
|
+
result.errors.push(`Table "${table}": ${err?.message ?? String(err)}`);
|
|
24885
24928
|
}
|
|
24886
|
-
|
|
24887
|
-
|
|
24888
|
-
|
|
24889
|
-
|
|
24890
|
-
|
|
24891
|
-
|
|
24892
|
-
|
|
24893
|
-
|
|
24894
|
-
|
|
24895
|
-
|
|
24896
|
-
|
|
24897
|
-
|
|
24898
|
-
if (
|
|
24899
|
-
|
|
24900
|
-
} else {
|
|
24901
|
-
batchUpsertSqlite(target, table, columns, updateCols, pkColumns, batch);
|
|
24929
|
+
results.push(result);
|
|
24930
|
+
}
|
|
24931
|
+
} finally {
|
|
24932
|
+
if (sqliteTarget) {
|
|
24933
|
+
try {
|
|
24934
|
+
sqliteTarget.exec("PRAGMA foreign_keys = ON");
|
|
24935
|
+
} catch {}
|
|
24936
|
+
try {
|
|
24937
|
+
const violations = sqliteTarget.all("PRAGMA foreign_key_check");
|
|
24938
|
+
if (violations.length > 0) {
|
|
24939
|
+
const tables2 = [...new Set(violations.map((v) => v.table))];
|
|
24940
|
+
const msg = `FK integrity check: ${violations.length} violation(s) in table(s): ${tables2.join(", ")}`;
|
|
24941
|
+
if (results.length > 0) {
|
|
24942
|
+
results[results.length - 1].errors.push(msg);
|
|
24902
24943
|
}
|
|
24903
|
-
result.rowsWritten += batch.length;
|
|
24904
|
-
} catch (err) {
|
|
24905
|
-
result.errors.push(`Batch at offset ${offset}: ${err?.message ?? String(err)}`);
|
|
24906
24944
|
}
|
|
24907
|
-
|
|
24908
|
-
table,
|
|
24909
|
-
phase: "writing",
|
|
24910
|
-
rowsRead: result.rowsRead,
|
|
24911
|
-
rowsWritten: result.rowsWritten,
|
|
24912
|
-
totalTables: tables.length,
|
|
24913
|
-
currentTableIndex: i
|
|
24914
|
-
});
|
|
24915
|
-
}
|
|
24916
|
-
onProgress?.({
|
|
24917
|
-
table,
|
|
24918
|
-
phase: "done",
|
|
24919
|
-
rowsRead: result.rowsRead,
|
|
24920
|
-
rowsWritten: result.rowsWritten,
|
|
24921
|
-
totalTables: tables.length,
|
|
24922
|
-
currentTableIndex: i
|
|
24923
|
-
});
|
|
24924
|
-
} catch (err) {
|
|
24925
|
-
result.errors.push(`Table "${table}": ${err?.message ?? String(err)}`);
|
|
24945
|
+
} catch {}
|
|
24926
24946
|
}
|
|
24927
|
-
results.push(result);
|
|
24928
|
-
}
|
|
24929
|
-
if (!isAsyncAdapter(target)) {
|
|
24930
|
-
try {
|
|
24931
|
-
target.run("PRAGMA foreign_keys = ON");
|
|
24932
|
-
} catch {}
|
|
24933
24947
|
}
|
|
24934
24948
|
return results;
|
|
24935
24949
|
}
|
package/dist/sync.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAMnD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;AAEpE,MAAM,WAAW,WAAW;IAC1B,sBAAsB;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,kCAAkC;IAClC,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAClC,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAMD;;;GAGG;AACH,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,SAAS,EAChB,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,EAAE,CAAC,CAGvB;AAMD;;;GAGG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,EAAE,CAAC,CAGvB;
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAMnD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;AAEpE,MAAM,WAAW,WAAW;IAC1B,sBAAsB;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,kCAAkC;IAClC,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAClC,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAMD;;;GAGG;AACH,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,SAAS,EAChB,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,EAAE,CAAC,CAGvB;AAMD;;;GAGG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,EAAE,CAAC,CAGvB;AAymBD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM,EAAE,CAKxD;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAKxE"}
|
package/package.json
CHANGED