@hasna/cloud 0.1.10 → 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 -82
- package/dist/index.js +109 -82
- package/dist/mcp/index.js +109 -82
- package/dist/sync.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -11452,47 +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
|
-
|
|
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
|
+
}
|
|
11496
11549
|
onProgress?.({
|
|
11497
11550
|
table,
|
|
11498
11551
|
phase: "writing",
|
|
@@ -11501,18 +11554,27 @@ async function syncTransfer(source, target, options, _direction) {
|
|
|
11501
11554
|
totalTables: tables.length,
|
|
11502
11555
|
currentTableIndex: i
|
|
11503
11556
|
});
|
|
11557
|
+
const updateCols = columns.filter((c) => !pkColumns.includes(c));
|
|
11504
11558
|
for (let offset = 0;offset < rows.length; offset += batchSize) {
|
|
11505
11559
|
const batch = rows.slice(offset, offset + batchSize);
|
|
11506
11560
|
try {
|
|
11507
11561
|
if (isAsyncAdapter(target)) {
|
|
11508
|
-
await
|
|
11562
|
+
await batchUpsertPg(target, table, columns, updateCols, pkColumns, batch);
|
|
11509
11563
|
} else {
|
|
11510
|
-
|
|
11564
|
+
batchUpsertSqlite(target, table, columns, updateCols, pkColumns, batch);
|
|
11511
11565
|
}
|
|
11512
11566
|
result.rowsWritten += batch.length;
|
|
11513
11567
|
} catch (err) {
|
|
11514
11568
|
result.errors.push(`Batch at offset ${offset}: ${err?.message ?? String(err)}`);
|
|
11515
11569
|
}
|
|
11570
|
+
onProgress?.({
|
|
11571
|
+
table,
|
|
11572
|
+
phase: "writing",
|
|
11573
|
+
rowsRead: result.rowsRead,
|
|
11574
|
+
rowsWritten: result.rowsWritten,
|
|
11575
|
+
totalTables: tables.length,
|
|
11576
|
+
currentTableIndex: i
|
|
11577
|
+
});
|
|
11516
11578
|
}
|
|
11517
11579
|
onProgress?.({
|
|
11518
11580
|
table,
|
|
@@ -11522,62 +11584,27 @@ async function syncTransfer(source, target, options, _direction) {
|
|
|
11522
11584
|
totalTables: tables.length,
|
|
11523
11585
|
currentTableIndex: i
|
|
11524
11586
|
});
|
|
11525
|
-
|
|
11526
|
-
|
|
11527
|
-
}
|
|
11528
|
-
const missingPks = pkColumns.filter((pk) => !columns.includes(pk));
|
|
11529
|
-
if (missingPks.length > 0) {
|
|
11530
|
-
result.errors.push(`Table "${table}" missing PK columns in data: ${missingPks.join(", ")} — skipping`);
|
|
11531
|
-
results.push(result);
|
|
11532
|
-
continue;
|
|
11587
|
+
} catch (err) {
|
|
11588
|
+
result.errors.push(`Table "${table}": ${err?.message ?? String(err)}`);
|
|
11533
11589
|
}
|
|
11534
|
-
|
|
11535
|
-
|
|
11536
|
-
|
|
11537
|
-
|
|
11538
|
-
|
|
11539
|
-
|
|
11540
|
-
|
|
11541
|
-
|
|
11542
|
-
|
|
11543
|
-
|
|
11544
|
-
|
|
11545
|
-
|
|
11546
|
-
if (
|
|
11547
|
-
|
|
11548
|
-
} else {
|
|
11549
|
-
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);
|
|
11550
11604
|
}
|
|
11551
|
-
result.rowsWritten += batch.length;
|
|
11552
|
-
} catch (err) {
|
|
11553
|
-
result.errors.push(`Batch at offset ${offset}: ${err?.message ?? String(err)}`);
|
|
11554
11605
|
}
|
|
11555
|
-
|
|
11556
|
-
table,
|
|
11557
|
-
phase: "writing",
|
|
11558
|
-
rowsRead: result.rowsRead,
|
|
11559
|
-
rowsWritten: result.rowsWritten,
|
|
11560
|
-
totalTables: tables.length,
|
|
11561
|
-
currentTableIndex: i
|
|
11562
|
-
});
|
|
11563
|
-
}
|
|
11564
|
-
onProgress?.({
|
|
11565
|
-
table,
|
|
11566
|
-
phase: "done",
|
|
11567
|
-
rowsRead: result.rowsRead,
|
|
11568
|
-
rowsWritten: result.rowsWritten,
|
|
11569
|
-
totalTables: tables.length,
|
|
11570
|
-
currentTableIndex: i
|
|
11571
|
-
});
|
|
11572
|
-
} catch (err) {
|
|
11573
|
-
result.errors.push(`Table "${table}": ${err?.message ?? String(err)}`);
|
|
11606
|
+
} catch {}
|
|
11574
11607
|
}
|
|
11575
|
-
results.push(result);
|
|
11576
|
-
}
|
|
11577
|
-
if (!isAsyncAdapter(target)) {
|
|
11578
|
-
try {
|
|
11579
|
-
target.run("PRAGMA foreign_keys = ON");
|
|
11580
|
-
} catch {}
|
|
11581
11608
|
}
|
|
11582
11609
|
return results;
|
|
11583
11610
|
}
|
package/dist/index.js
CHANGED
|
@@ -9444,47 +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
|
-
|
|
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
|
+
}
|
|
9488
9541
|
onProgress?.({
|
|
9489
9542
|
table,
|
|
9490
9543
|
phase: "writing",
|
|
@@ -9493,18 +9546,27 @@ async function syncTransfer(source, target, options, _direction) {
|
|
|
9493
9546
|
totalTables: tables.length,
|
|
9494
9547
|
currentTableIndex: i
|
|
9495
9548
|
});
|
|
9549
|
+
const updateCols = columns.filter((c) => !pkColumns.includes(c));
|
|
9496
9550
|
for (let offset = 0;offset < rows.length; offset += batchSize) {
|
|
9497
9551
|
const batch = rows.slice(offset, offset + batchSize);
|
|
9498
9552
|
try {
|
|
9499
9553
|
if (isAsyncAdapter(target)) {
|
|
9500
|
-
await
|
|
9554
|
+
await batchUpsertPg(target, table, columns, updateCols, pkColumns, batch);
|
|
9501
9555
|
} else {
|
|
9502
|
-
|
|
9556
|
+
batchUpsertSqlite(target, table, columns, updateCols, pkColumns, batch);
|
|
9503
9557
|
}
|
|
9504
9558
|
result.rowsWritten += batch.length;
|
|
9505
9559
|
} catch (err) {
|
|
9506
9560
|
result.errors.push(`Batch at offset ${offset}: ${err?.message ?? String(err)}`);
|
|
9507
9561
|
}
|
|
9562
|
+
onProgress?.({
|
|
9563
|
+
table,
|
|
9564
|
+
phase: "writing",
|
|
9565
|
+
rowsRead: result.rowsRead,
|
|
9566
|
+
rowsWritten: result.rowsWritten,
|
|
9567
|
+
totalTables: tables.length,
|
|
9568
|
+
currentTableIndex: i
|
|
9569
|
+
});
|
|
9508
9570
|
}
|
|
9509
9571
|
onProgress?.({
|
|
9510
9572
|
table,
|
|
@@ -9514,62 +9576,27 @@ async function syncTransfer(source, target, options, _direction) {
|
|
|
9514
9576
|
totalTables: tables.length,
|
|
9515
9577
|
currentTableIndex: i
|
|
9516
9578
|
});
|
|
9517
|
-
|
|
9518
|
-
|
|
9519
|
-
}
|
|
9520
|
-
const missingPks = pkColumns.filter((pk) => !columns.includes(pk));
|
|
9521
|
-
if (missingPks.length > 0) {
|
|
9522
|
-
result.errors.push(`Table "${table}" missing PK columns in data: ${missingPks.join(", ")} — skipping`);
|
|
9523
|
-
results.push(result);
|
|
9524
|
-
continue;
|
|
9579
|
+
} catch (err) {
|
|
9580
|
+
result.errors.push(`Table "${table}": ${err?.message ?? String(err)}`);
|
|
9525
9581
|
}
|
|
9526
|
-
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9530
|
-
|
|
9531
|
-
|
|
9532
|
-
|
|
9533
|
-
|
|
9534
|
-
|
|
9535
|
-
|
|
9536
|
-
|
|
9537
|
-
|
|
9538
|
-
if (
|
|
9539
|
-
|
|
9540
|
-
} else {
|
|
9541
|
-
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);
|
|
9542
9596
|
}
|
|
9543
|
-
result.rowsWritten += batch.length;
|
|
9544
|
-
} catch (err) {
|
|
9545
|
-
result.errors.push(`Batch at offset ${offset}: ${err?.message ?? String(err)}`);
|
|
9546
9597
|
}
|
|
9547
|
-
|
|
9548
|
-
table,
|
|
9549
|
-
phase: "writing",
|
|
9550
|
-
rowsRead: result.rowsRead,
|
|
9551
|
-
rowsWritten: result.rowsWritten,
|
|
9552
|
-
totalTables: tables.length,
|
|
9553
|
-
currentTableIndex: i
|
|
9554
|
-
});
|
|
9555
|
-
}
|
|
9556
|
-
onProgress?.({
|
|
9557
|
-
table,
|
|
9558
|
-
phase: "done",
|
|
9559
|
-
rowsRead: result.rowsRead,
|
|
9560
|
-
rowsWritten: result.rowsWritten,
|
|
9561
|
-
totalTables: tables.length,
|
|
9562
|
-
currentTableIndex: i
|
|
9563
|
-
});
|
|
9564
|
-
} catch (err) {
|
|
9565
|
-
result.errors.push(`Table "${table}": ${err?.message ?? String(err)}`);
|
|
9598
|
+
} catch {}
|
|
9566
9599
|
}
|
|
9567
|
-
results.push(result);
|
|
9568
|
-
}
|
|
9569
|
-
if (!isAsyncAdapter(target)) {
|
|
9570
|
-
try {
|
|
9571
|
-
target.run("PRAGMA foreign_keys = ON");
|
|
9572
|
-
} catch {}
|
|
9573
9600
|
}
|
|
9574
9601
|
return results;
|
|
9575
9602
|
}
|
package/dist/mcp/index.js
CHANGED
|
@@ -24791,47 +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
|
-
|
|
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
|
+
}
|
|
24835
24888
|
onProgress?.({
|
|
24836
24889
|
table,
|
|
24837
24890
|
phase: "writing",
|
|
@@ -24840,18 +24893,27 @@ async function syncTransfer(source, target, options, _direction) {
|
|
|
24840
24893
|
totalTables: tables.length,
|
|
24841
24894
|
currentTableIndex: i
|
|
24842
24895
|
});
|
|
24896
|
+
const updateCols = columns.filter((c) => !pkColumns.includes(c));
|
|
24843
24897
|
for (let offset = 0;offset < rows.length; offset += batchSize) {
|
|
24844
24898
|
const batch = rows.slice(offset, offset + batchSize);
|
|
24845
24899
|
try {
|
|
24846
24900
|
if (isAsyncAdapter(target)) {
|
|
24847
|
-
await
|
|
24901
|
+
await batchUpsertPg(target, table, columns, updateCols, pkColumns, batch);
|
|
24848
24902
|
} else {
|
|
24849
|
-
|
|
24903
|
+
batchUpsertSqlite(target, table, columns, updateCols, pkColumns, batch);
|
|
24850
24904
|
}
|
|
24851
24905
|
result.rowsWritten += batch.length;
|
|
24852
24906
|
} catch (err) {
|
|
24853
24907
|
result.errors.push(`Batch at offset ${offset}: ${err?.message ?? String(err)}`);
|
|
24854
24908
|
}
|
|
24909
|
+
onProgress?.({
|
|
24910
|
+
table,
|
|
24911
|
+
phase: "writing",
|
|
24912
|
+
rowsRead: result.rowsRead,
|
|
24913
|
+
rowsWritten: result.rowsWritten,
|
|
24914
|
+
totalTables: tables.length,
|
|
24915
|
+
currentTableIndex: i
|
|
24916
|
+
});
|
|
24855
24917
|
}
|
|
24856
24918
|
onProgress?.({
|
|
24857
24919
|
table,
|
|
@@ -24861,62 +24923,27 @@ async function syncTransfer(source, target, options, _direction) {
|
|
|
24861
24923
|
totalTables: tables.length,
|
|
24862
24924
|
currentTableIndex: i
|
|
24863
24925
|
});
|
|
24864
|
-
|
|
24865
|
-
|
|
24866
|
-
}
|
|
24867
|
-
const missingPks = pkColumns.filter((pk) => !columns.includes(pk));
|
|
24868
|
-
if (missingPks.length > 0) {
|
|
24869
|
-
result.errors.push(`Table "${table}" missing PK columns in data: ${missingPks.join(", ")} — skipping`);
|
|
24870
|
-
results.push(result);
|
|
24871
|
-
continue;
|
|
24926
|
+
} catch (err) {
|
|
24927
|
+
result.errors.push(`Table "${table}": ${err?.message ?? String(err)}`);
|
|
24872
24928
|
}
|
|
24873
|
-
|
|
24874
|
-
|
|
24875
|
-
|
|
24876
|
-
|
|
24877
|
-
|
|
24878
|
-
|
|
24879
|
-
|
|
24880
|
-
|
|
24881
|
-
|
|
24882
|
-
|
|
24883
|
-
|
|
24884
|
-
|
|
24885
|
-
if (
|
|
24886
|
-
|
|
24887
|
-
} else {
|
|
24888
|
-
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);
|
|
24889
24943
|
}
|
|
24890
|
-
result.rowsWritten += batch.length;
|
|
24891
|
-
} catch (err) {
|
|
24892
|
-
result.errors.push(`Batch at offset ${offset}: ${err?.message ?? String(err)}`);
|
|
24893
24944
|
}
|
|
24894
|
-
|
|
24895
|
-
table,
|
|
24896
|
-
phase: "writing",
|
|
24897
|
-
rowsRead: result.rowsRead,
|
|
24898
|
-
rowsWritten: result.rowsWritten,
|
|
24899
|
-
totalTables: tables.length,
|
|
24900
|
-
currentTableIndex: i
|
|
24901
|
-
});
|
|
24902
|
-
}
|
|
24903
|
-
onProgress?.({
|
|
24904
|
-
table,
|
|
24905
|
-
phase: "done",
|
|
24906
|
-
rowsRead: result.rowsRead,
|
|
24907
|
-
rowsWritten: result.rowsWritten,
|
|
24908
|
-
totalTables: tables.length,
|
|
24909
|
-
currentTableIndex: i
|
|
24910
|
-
});
|
|
24911
|
-
} catch (err) {
|
|
24912
|
-
result.errors.push(`Table "${table}": ${err?.message ?? String(err)}`);
|
|
24945
|
+
} catch {}
|
|
24913
24946
|
}
|
|
24914
|
-
results.push(result);
|
|
24915
|
-
}
|
|
24916
|
-
if (!isAsyncAdapter(target)) {
|
|
24917
|
-
try {
|
|
24918
|
-
target.run("PRAGMA foreign_keys = ON");
|
|
24919
|
-
} catch {}
|
|
24920
24947
|
}
|
|
24921
24948
|
return results;
|
|
24922
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