@hasna/cloud 0.1.3 → 0.1.5

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/adapter.d.ts CHANGED
@@ -26,6 +26,8 @@ export declare class SqliteAdapter implements DbAdapter {
26
26
  get(sql: string, ...params: any[]): any;
27
27
  all(sql: string, ...params: any[]): any[];
28
28
  exec(sql: string): void;
29
+ /** Passthrough to bun:sqlite's .query() for compatibility with code that uses db.query() */
30
+ query(sql: string): import("bun:sqlite").Statement<unknown, import("bun:sqlite").SQLQueryBindings[] | [null] | [string] | [number] | [bigint] | [false] | [true] | [Uint8Array<ArrayBufferLike>] | [Uint8ClampedArray<ArrayBufferLike>] | [Uint16Array<ArrayBufferLike>] | [Uint32Array<ArrayBufferLike>] | [Int8Array<ArrayBufferLike>] | [Int16Array<ArrayBufferLike>] | [Int32Array<ArrayBufferLike>] | [BigUint64Array<ArrayBufferLike>] | [BigInt64Array<ArrayBufferLike>] | [Float16Array<ArrayBufferLike>] | [Float32Array<ArrayBufferLike>] | [Float64Array<ArrayBufferLike>] | [Record<string, string | number | bigint | boolean | NodeJS.TypedArray<ArrayBufferLike> | null>]>;
29
31
  prepare(sql: string): PreparedStatement;
30
32
  close(): void;
31
33
  transaction<T>(fn: () => T): T;
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import type { DbAdapter } from "./adapter.js";
2
+ export interface AutoSyncConfig {
3
+ auto_sync_on_start: boolean;
4
+ auto_sync_on_stop: boolean;
5
+ }
6
+ export interface AutoSyncContext {
7
+ serviceName: string;
8
+ local: DbAdapter;
9
+ remote: DbAdapter;
10
+ tables: string[];
11
+ config: AutoSyncConfig;
12
+ }
13
+ export interface AutoSyncResult {
14
+ event: "start" | "stop";
15
+ direction: "pull" | "push";
16
+ success: boolean;
17
+ tables_synced: number;
18
+ total_rows_synced: number;
19
+ errors: string[];
20
+ }
21
+ /**
22
+ * Read auto-sync configuration from `~/.hasna/cloud/config.json`.
23
+ * Falls back to defaults if the file does not exist or is malformed.
24
+ */
25
+ export declare function getAutoSyncConfig(): AutoSyncConfig;
26
+ /**
27
+ * Set up auto-sync hooks for a service's MCP server.
28
+ *
29
+ * - On connect: if `auto_sync_on_start` and mode is `hybrid` or `cloud`,
30
+ * pull from cloud to local.
31
+ * - On disconnect/SIGTERM: if `auto_sync_on_stop` and mode is `hybrid` or `cloud`,
32
+ * push from local to cloud.
33
+ *
34
+ * @param serviceName - The service identifier.
35
+ * @param server - The MCP server instance (any object with `onconnect`/`ondisconnect` events).
36
+ * @param local - The local database adapter.
37
+ * @param remote - The remote database adapter.
38
+ * @param tables - Tables to sync.
39
+ * @returns An object with methods to manually trigger start/stop syncs.
40
+ */
41
+ export declare function setupAutoSync(serviceName: string, server: any, local: DbAdapter, remote: DbAdapter, tables: string[]): {
42
+ syncOnStart: () => AutoSyncResult | null;
43
+ syncOnStop: () => AutoSyncResult | null;
44
+ config: AutoSyncConfig;
45
+ };
46
+ /**
47
+ * Enable auto-sync for a service. Simplified entry point that services
48
+ * can call with minimal configuration.
49
+ *
50
+ * @param serviceName - The service name (used for logging context).
51
+ * @param mcpServer - The MCP server instance.
52
+ * @param local - The local database adapter.
53
+ * @param remote - The remote database adapter.
54
+ * @param tables - Tables to sync on start/stop.
55
+ */
56
+ export declare function enableAutoSync(serviceName: string, mcpServer: any, local: DbAdapter, remote: DbAdapter, tables: string[]): void;
57
+ //# sourceMappingURL=auto-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-sync.d.ts","sourceRoot":"","sources":["../src/auto-sync.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAQ9C,MAAM,WAAW,cAAc;IAC7B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAaD;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,CAmBlD;AAwFD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,GAAG,EACX,KAAK,EAAE,SAAS,EAChB,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EAAE,GACf;IACD,WAAW,EAAE,MAAM,cAAc,GAAG,IAAI,CAAC;IACzC,UAAU,EAAE,MAAM,cAAc,GAAG,IAAI,CAAC;IACxC,MAAM,EAAE,cAAc,CAAC;CACxB,CAiDA;AAMD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,GAAG,EACd,KAAK,EAAE,SAAS,EAChB,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EAAE,GACf,IAAI,CAEN"}
package/dist/cli/index.js CHANGED
@@ -2191,7 +2191,7 @@ var require_arrayParser = __commonJS((exports, module) => {
2191
2191
  };
2192
2192
  });
2193
2193
 
2194
- // node_modules/postgres-date/index.js
2194
+ // node_modules/pg-types/node_modules/postgres-date/index.js
2195
2195
  var require_postgres_date = __commonJS((exports, module) => {
2196
2196
  var DATE_TIME = /(\d{1,})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})(\.\d{1,})?.*?( BC)?$/;
2197
2197
  var DATE = /^(\d{1,})-(\d{2})-(\d{2})( BC)?$/;
@@ -2293,7 +2293,7 @@ var require_mutable = __commonJS((exports, module) => {
2293
2293
  }
2294
2294
  });
2295
2295
 
2296
- // node_modules/postgres-interval/index.js
2296
+ // node_modules/pg-types/node_modules/postgres-interval/index.js
2297
2297
  var require_postgres_interval = __commonJS((exports, module) => {
2298
2298
  var extend = require_mutable();
2299
2299
  module.exports = PostgresInterval;
@@ -2385,7 +2385,7 @@ var require_postgres_interval = __commonJS((exports, module) => {
2385
2385
  }
2386
2386
  });
2387
2387
 
2388
- // node_modules/postgres-bytea/index.js
2388
+ // node_modules/pg-types/node_modules/postgres-bytea/index.js
2389
2389
  var require_postgres_bytea = __commonJS((exports, module) => {
2390
2390
  var bufferFrom = Buffer.from || Buffer;
2391
2391
  module.exports = function parseBytea(input) {
@@ -11026,6 +11026,9 @@ class SqliteAdapter {
11026
11026
  exec(sql) {
11027
11027
  this.db.exec(sql);
11028
11028
  }
11029
+ query(sql) {
11030
+ return this.db.query(sql);
11031
+ }
11029
11032
  prepare(sql) {
11030
11033
  const stmt = this.db.prepare(sql);
11031
11034
  return {
@@ -11257,17 +11260,88 @@ function createDatabase(options) {
11257
11260
  }
11258
11261
 
11259
11262
  // src/sync.ts
11260
- function syncPush(local, cloud, options) {
11261
- return syncTransfer(local, cloud, options, "push");
11263
+ async function syncPush(local, remote, options) {
11264
+ const orderedTables = await getTableOrder(remote, options.tables);
11265
+ return syncTransfer(local, remote, { ...options, tables: orderedTables }, "push");
11266
+ }
11267
+ async function syncPull(remote, local, options) {
11268
+ const orderedTables = await getTableOrder(remote, options.tables);
11269
+ return syncTransfer(remote, local, { ...options, tables: orderedTables }, "pull");
11270
+ }
11271
+ async function getTableOrder(remote, tables) {
11272
+ if (tables.length <= 1)
11273
+ return tables;
11274
+ try {
11275
+ const fks = await remote.all(`
11276
+ SELECT DISTINCT
11277
+ tc.table_name AS source_table,
11278
+ ccu.table_name AS referenced_table
11279
+ FROM information_schema.table_constraints tc
11280
+ JOIN information_schema.constraint_column_usage ccu
11281
+ ON tc.constraint_name = ccu.constraint_name
11282
+ AND tc.table_schema = ccu.table_schema
11283
+ WHERE tc.constraint_type = 'FOREIGN KEY'
11284
+ AND tc.table_schema = 'public'
11285
+ `);
11286
+ if (fks.length > 0) {
11287
+ return topoSort(tables, fks);
11288
+ }
11289
+ } catch {}
11290
+ return heuristicOrder(tables);
11291
+ }
11292
+ function topoSort(tables, fks) {
11293
+ const tableSet = new Set(tables);
11294
+ const deps = new Map;
11295
+ for (const t of tables) {
11296
+ deps.set(t, new Set);
11297
+ }
11298
+ for (const fk of fks) {
11299
+ if (tableSet.has(fk.source_table) && tableSet.has(fk.referenced_table)) {
11300
+ deps.get(fk.source_table).add(fk.referenced_table);
11301
+ }
11302
+ }
11303
+ const sorted = [];
11304
+ const visited = new Set;
11305
+ const visiting = new Set;
11306
+ function visit(table) {
11307
+ if (visited.has(table))
11308
+ return;
11309
+ if (visiting.has(table)) {
11310
+ sorted.push(table);
11311
+ visited.add(table);
11312
+ return;
11313
+ }
11314
+ visiting.add(table);
11315
+ const tableDeps = deps.get(table) ?? new Set;
11316
+ for (const dep of tableDeps) {
11317
+ visit(dep);
11318
+ }
11319
+ visiting.delete(table);
11320
+ visited.add(table);
11321
+ sorted.push(table);
11322
+ }
11323
+ for (const t of tables) {
11324
+ visit(t);
11325
+ }
11326
+ return sorted;
11262
11327
  }
11263
- function syncPull(local, cloud, options) {
11264
- return syncTransfer(cloud, local, options, "pull");
11328
+ function heuristicOrder(tables) {
11329
+ const sorted = [...tables].sort((a, b) => {
11330
+ const aIsChild = a.includes("_") && tables.some((t) => a.startsWith(t + "_") || a.endsWith("_" + t));
11331
+ const bIsChild = b.includes("_") && tables.some((t) => b.startsWith(t + "_") || b.endsWith("_" + t));
11332
+ if (aIsChild && !bIsChild)
11333
+ return 1;
11334
+ if (!aIsChild && bIsChild)
11335
+ return -1;
11336
+ return a.localeCompare(b);
11337
+ });
11338
+ return sorted;
11265
11339
  }
11266
- function syncTransfer(source, target, options, _direction) {
11340
+ async function syncTransfer(source, target, options, _direction) {
11267
11341
  const {
11268
11342
  tables,
11269
11343
  onProgress,
11270
- batchSize = 500,
11344
+ batchSize = 100,
11271
11345
  conflictColumn = "updated_at",
11272
11346
  primaryKey = "id"
11273
11347
  } = options;
@@ -11290,7 +11364,7 @@ function syncTransfer(source, target, options, _direction) {
11290
11364
  totalTables: tables.length,
11291
11365
  currentTableIndex: i
11292
11366
  });
11293
- const rows = source.all(`SELECT * FROM "${table}"`);
11367
+ const rows = await readAll(source, `SELECT * FROM "${table}"`);
11294
11368
  result.rowsRead = rows.length;
11295
11369
  if (rows.length === 0) {
11296
11370
  onProgress?.({
@@ -11305,7 +11379,6 @@ function syncTransfer(source, target, options, _direction) {
11305
11379
  continue;
11306
11380
  }
11307
11381
  const columns = Object.keys(rows[0]);
11308
- const hasConflictCol = columns.includes(conflictColumn);
11309
11382
  const hasPrimaryKey = columns.includes(primaryKey);
11310
11383
  if (!hasPrimaryKey) {
11311
11384
  result.errors.push(`Table "${table}" has no "${primaryKey}" column — skipping`);
@@ -11320,34 +11393,18 @@ function syncTransfer(source, target, options, _direction) {
11320
11393
  totalTables: tables.length,
11321
11394
  currentTableIndex: i
11322
11395
  });
11396
+ const updateCols = columns.filter((c) => c !== primaryKey);
11323
11397
  for (let offset = 0;offset < rows.length; offset += batchSize) {
11324
11398
  const batch = rows.slice(offset, offset + batchSize);
11325
- for (const row of batch) {
11326
- try {
11327
- const existing = target.get(`SELECT "${primaryKey}"${hasConflictCol ? `, "${conflictColumn}"` : ""} FROM "${table}" WHERE "${primaryKey}" = ?`, row[primaryKey]);
11328
- if (existing) {
11329
- if (hasConflictCol && existing[conflictColumn] && row[conflictColumn]) {
11330
- const existingTime = new Date(existing[conflictColumn]).getTime();
11331
- const incomingTime = new Date(row[conflictColumn]).getTime();
11332
- if (existingTime >= incomingTime) {
11333
- result.rowsSkipped++;
11334
- continue;
11335
- }
11336
- }
11337
- const setClauses = columns.filter((c) => c !== primaryKey).map((c) => `"${c}" = ?`).join(", ");
11338
- const values = columns.filter((c) => c !== primaryKey).map((c) => row[c]);
11339
- values.push(row[primaryKey]);
11340
- target.run(`UPDATE "${table}" SET ${setClauses} WHERE "${primaryKey}" = ?`, ...values);
11341
- } else {
11342
- const placeholders = columns.map(() => "?").join(", ");
11343
- const colList = columns.map((c) => `"${c}"`).join(", ");
11344
- const values = columns.map((c) => row[c]);
11345
- target.run(`INSERT INTO "${table}" (${colList}) VALUES (${placeholders})`, ...values);
11346
- }
11347
- result.rowsWritten++;
11348
- } catch (err) {
11349
- result.errors.push(`Row ${row[primaryKey]}: ${err?.message ?? String(err)}`);
11399
+ try {
11400
+ if (isAsyncAdapter(target)) {
11401
+ await batchUpsertPg(target, table, columns, updateCols, primaryKey, batch);
11402
+ } else {
11403
+ batchUpsertSqlite(target, table, columns, updateCols, primaryKey, batch);
11350
11404
  }
11405
+ result.rowsWritten += batch.length;
11406
+ } catch (err) {
11407
+ result.errors.push(`Batch at offset ${offset}: ${err?.message ?? String(err)}`);
11351
11408
  }
11352
11409
  onProgress?.({
11353
11410
  table,
@@ -11373,10 +11430,46 @@ function syncTransfer(source, target, options, _direction) {
11373
11430
  }
11374
11431
  return results;
11375
11432
  }
11433
+ async function batchUpsertPg(target, table, columns, updateCols, primaryKey, batch) {
11434
+ if (batch.length === 0)
11435
+ return;
11436
+ const colList = columns.map((c) => `"${c}"`).join(", ");
11437
+ const valuePlaceholders = batch.map((_, rowIdx) => {
11438
+ const offset = rowIdx * columns.length;
11439
+ return `(${columns.map((_2, colIdx) => `$${offset + colIdx + 1}`).join(", ")})`;
11440
+ }).join(", ");
11441
+ const setClause = updateCols.length > 0 ? updateCols.map((c) => `"${c}" = EXCLUDED."${c}"`).join(", ") : `"${primaryKey}" = EXCLUDED."${primaryKey}"`;
11442
+ const sql = `INSERT INTO "${table}" (${colList}) VALUES ${valuePlaceholders}
11443
+ ON CONFLICT ("${primaryKey}") DO UPDATE SET ${setClause}`;
11444
+ const params = batch.flatMap((row) => columns.map((c) => row[c] ?? null));
11445
+ await target.run(sql, ...params);
11446
+ }
11447
+ function batchUpsertSqlite(target, table, columns, updateCols, primaryKey, batch) {
11448
+ if (batch.length === 0)
11449
+ return;
11450
+ const colList = columns.map((c) => `"${c}"`).join(", ");
11451
+ const valuePlaceholders = batch.map(() => `(${columns.map(() => "?").join(", ")})`).join(", ");
11452
+ const setClause = updateCols.length > 0 ? updateCols.map((c) => `"${c}" = EXCLUDED."${c}"`).join(", ") : `"${primaryKey}" = EXCLUDED."${primaryKey}"`;
11453
+ const sql = `INSERT INTO "${table}" (${colList}) VALUES ${valuePlaceholders}
11454
+ ON CONFLICT ("${primaryKey}") DO UPDATE SET ${setClause}`;
11455
+ const params = batch.flatMap((row) => columns.map((c) => row[c] ?? null));
11456
+ target.run(sql, ...params);
11457
+ }
11458
+ function isAsyncAdapter(adapter) {
11459
+ return adapter.constructor.name === "PgAdapterAsync" || typeof adapter.raw?.connect === "function";
11460
+ }
11461
+ async function readAll(adapter, sql) {
11462
+ const result = adapter.all(sql);
11463
+ return result instanceof Promise ? await result : result;
11464
+ }
11376
11465
  function listSqliteTables(db) {
11377
11466
  const rows = db.all(`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name`);
11378
11467
  return rows.map((r) => r.name);
11379
11468
  }
11469
+ async function listPgTables(db) {
11470
+ const rows = await db.all(`SELECT tablename FROM pg_tables WHERE schemaname = 'public' ORDER BY tablename`);
11471
+ return rows.map((r) => r.tablename);
11472
+ }
11380
11473
 
11381
11474
  // src/feedback.ts
11382
11475
  import { hostname } from "os";
@@ -11549,6 +11642,9 @@ class SqliteAdapter2 {
11549
11642
  exec(sql) {
11550
11643
  this.db.exec(sql);
11551
11644
  }
11645
+ query(sql) {
11646
+ return this.db.query(sql);
11647
+ }
11552
11648
  prepare(sql) {
11553
11649
  const stmt = this.db.prepare(sql);
11554
11650
  return {
@@ -11578,10 +11674,8 @@ class SqliteAdapter2 {
11578
11674
  return this.db;
11579
11675
  }
11580
11676
  }
11581
-
11582
- class PgAdapter2 {
11677
+ class PgAdapterAsync {
11583
11678
  pool;
11584
- _client = null;
11585
11679
  constructor(arg) {
11586
11680
  if (typeof arg === "string") {
11587
11681
  this.pool = new esm_default.Pool({ connectionString: arg });
@@ -11589,118 +11683,47 @@ class PgAdapter2 {
11589
11683
  this.pool = arg;
11590
11684
  }
11591
11685
  }
11592
- runSync(fn) {
11593
- let result;
11594
- let error;
11595
- let done = false;
11596
- fn().then((r) => {
11597
- result = r;
11598
- done = true;
11599
- }).catch((e) => {
11600
- error = e;
11601
- done = true;
11602
- });
11603
- const deadline = Date.now() + 30000;
11604
- while (!done && Date.now() < deadline) {
11605
- Bun.sleepSync(1);
11606
- }
11607
- if (error)
11608
- throw error;
11609
- if (!done)
11610
- throw new Error("PgAdapter: query timed out (30s)");
11611
- return result;
11612
- }
11613
- run(sql, ...params) {
11686
+ async run(sql, ...params) {
11614
11687
  const pgSql = translateSql(sql, "pg");
11615
11688
  const pgParams = translateParams(params);
11616
- return this.runSync(async () => {
11617
- const res = await this.pool.query(pgSql, pgParams);
11618
- return {
11619
- changes: res.rowCount ?? 0,
11620
- lastInsertRowid: res.rows?.[0]?.id ?? 0
11621
- };
11622
- });
11689
+ const res = await this.pool.query(pgSql, pgParams);
11690
+ return {
11691
+ changes: res.rowCount ?? 0,
11692
+ lastInsertRowid: res.rows?.[0]?.id ?? 0
11693
+ };
11623
11694
  }
11624
- get(sql, ...params) {
11695
+ async get(sql, ...params) {
11625
11696
  const pgSql = translateSql(sql, "pg");
11626
11697
  const pgParams = translateParams(params);
11627
- return this.runSync(async () => {
11628
- const res = await this.pool.query(pgSql, pgParams);
11629
- return res.rows[0] ?? null;
11630
- });
11698
+ const res = await this.pool.query(pgSql, pgParams);
11699
+ return res.rows[0] ?? null;
11631
11700
  }
11632
- all(sql, ...params) {
11701
+ async all(sql, ...params) {
11633
11702
  const pgSql = translateSql(sql, "pg");
11634
11703
  const pgParams = translateParams(params);
11635
- return this.runSync(async () => {
11636
- const res = await this.pool.query(pgSql, pgParams);
11637
- return res.rows;
11638
- });
11704
+ const res = await this.pool.query(pgSql, pgParams);
11705
+ return res.rows;
11639
11706
  }
11640
- exec(sql) {
11707
+ async exec(sql) {
11641
11708
  const pgSql = translateSql(sql, "pg");
11642
- this.runSync(async () => {
11643
- await this.pool.query(pgSql);
11644
- });
11709
+ await this.pool.query(pgSql);
11645
11710
  }
11646
- prepare(sql) {
11647
- const pgSql = translateSql(sql, "pg");
11648
- const adapter = this;
11649
- return {
11650
- run(...params) {
11651
- const pgParams = translateParams(params);
11652
- return adapter.runSync(async () => {
11653
- const res = await adapter.pool.query(pgSql, pgParams);
11654
- return {
11655
- changes: res.rowCount ?? 0,
11656
- lastInsertRowid: res.rows?.[0]?.id ?? 0
11657
- };
11658
- });
11659
- },
11660
- get(...params) {
11661
- const pgParams = translateParams(params);
11662
- return adapter.runSync(async () => {
11663
- const res = await adapter.pool.query(pgSql, pgParams);
11664
- return res.rows[0] ?? null;
11665
- });
11666
- },
11667
- all(...params) {
11668
- const pgParams = translateParams(params);
11669
- return adapter.runSync(async () => {
11670
- const res = await adapter.pool.query(pgSql, pgParams);
11671
- return res.rows;
11672
- });
11673
- },
11674
- finalize() {}
11675
- };
11711
+ async close() {
11712
+ await this.pool.end();
11676
11713
  }
11677
- close() {
11678
- this.runSync(async () => {
11679
- await this.pool.end();
11680
- });
11681
- }
11682
- transaction(fn) {
11683
- return this.runSync(async () => {
11684
- const client = await this.pool.connect();
11685
- try {
11686
- await client.query("BEGIN");
11687
- const origQuery = this.pool.query.bind(this.pool);
11688
- this.pool.query = client.query.bind(client);
11689
- let result;
11690
- try {
11691
- result = fn();
11692
- } finally {
11693
- this.pool.query = origQuery;
11694
- }
11695
- await client.query("COMMIT");
11696
- return result;
11697
- } catch (err) {
11698
- await client.query("ROLLBACK");
11699
- throw err;
11700
- } finally {
11701
- client.release();
11702
- }
11703
- });
11714
+ async transaction(fn) {
11715
+ const client = await this.pool.connect();
11716
+ try {
11717
+ await client.query("BEGIN");
11718
+ const result = await fn(client);
11719
+ await client.query("COMMIT");
11720
+ return result;
11721
+ } catch (err) {
11722
+ await client.query("ROLLBACK");
11723
+ throw err;
11724
+ } finally {
11725
+ client.release();
11726
+ }
11704
11727
  }
11705
11728
  get raw() {
11706
11729
  return this.pool;
@@ -11742,19 +11765,19 @@ program2.command("status").description("Show current cloud configuration and con
11742
11765
  Checking PostgreSQL connection...`);
11743
11766
  try {
11744
11767
  const connStr = getConnectionString("postgres");
11745
- const pg2 = new PgAdapter2(connStr);
11746
- const row = pg2.get("SELECT 1 as ok");
11768
+ const pg2 = new PgAdapterAsync(connStr);
11769
+ const row = await pg2.get("SELECT 1 as ok");
11747
11770
  if (row?.ok === 1) {
11748
11771
  console.log("PostgreSQL: connected");
11749
11772
  }
11750
- pg2.close();
11773
+ await pg2.close();
11751
11774
  } catch (err) {
11752
11775
  console.log("PostgreSQL: connection failed \u2014", err?.message);
11753
11776
  }
11754
11777
  }
11755
11778
  });
11756
11779
  var syncCmd = program2.command("sync").description("Sync data between local and cloud");
11757
- syncCmd.command("push").description("Push local data to cloud").requiredOption("--service <name>", "Service name").option("--tables <tables>", "Comma-separated table names (default: all)").action((opts) => {
11780
+ syncCmd.command("push").description("Push local data to cloud").requiredOption("--service <name>", "Service name").option("--tables <tables>", "Comma-separated table names (default: all)").action(async (opts) => {
11758
11781
  const config = getCloudConfig();
11759
11782
  if (config.mode === "local") {
11760
11783
  console.error("Error: mode is 'local'. Run `cloud setup --mode hybrid` or `--mode cloud` first.");
@@ -11775,8 +11798,8 @@ syncCmd.command("push").description("Push local data to cloud").requiredOption("
11775
11798
  }
11776
11799
  console.log(`Pushing ${tables.length} table(s) to cloud...`);
11777
11800
  const connStr = getConnectionString(opts.service);
11778
- const cloud = new PgAdapter2(connStr);
11779
- const results = syncPush(local, cloud, {
11801
+ const cloud = new PgAdapterAsync(connStr);
11802
+ const results = await syncPush(local, cloud, {
11780
11803
  tables,
11781
11804
  onProgress: (p) => {
11782
11805
  if (p.phase === "done") {
@@ -11785,7 +11808,7 @@ syncCmd.command("push").description("Push local data to cloud").requiredOption("
11785
11808
  }
11786
11809
  });
11787
11810
  local.close();
11788
- cloud.close();
11811
+ await cloud.close();
11789
11812
  const totalWritten = results.reduce((s, r) => s + r.rowsWritten, 0);
11790
11813
  const totalErrors = results.reduce((s, r) => s + r.errors.length, 0);
11791
11814
  console.log(`
@@ -11798,7 +11821,7 @@ Done. ${totalWritten} rows pushed, ${totalErrors} errors.`);
11798
11821
  }
11799
11822
  }
11800
11823
  });
11801
- syncCmd.command("pull").description("Pull cloud data to local").requiredOption("--service <name>", "Service name").option("--tables <tables>", "Comma-separated table names (default: all)").action((opts) => {
11824
+ syncCmd.command("pull").description("Pull cloud data to local").requiredOption("--service <name>", "Service name").option("--tables <tables>", "Comma-separated table names (default: all)").action(async (opts) => {
11802
11825
  const config = getCloudConfig();
11803
11826
  if (config.mode === "local") {
11804
11827
  console.error("Error: mode is 'local'. Run `cloud setup --mode hybrid` or `--mode cloud` first.");
@@ -11807,18 +11830,17 @@ syncCmd.command("pull").description("Pull cloud data to local").requiredOption("
11807
11830
  const dbPath = getDbPath2(opts.service);
11808
11831
  const local = new SqliteAdapter2(dbPath);
11809
11832
  const connStr = getConnectionString(opts.service);
11810
- const cloud = new PgAdapter2(connStr);
11833
+ const cloud = new PgAdapterAsync(connStr);
11811
11834
  let tables;
11812
11835
  if (opts.tables) {
11813
11836
  tables = opts.tables.split(",").map((t) => t.trim());
11814
11837
  } else {
11815
11838
  try {
11816
- const rows = cloud.all(`SELECT tablename FROM pg_tables WHERE schemaname = 'public' ORDER BY tablename`);
11817
- tables = rows.map((r) => r.tablename);
11839
+ tables = await listPgTables(cloud);
11818
11840
  } catch {
11819
11841
  console.error("Failed to list tables from cloud.");
11820
11842
  local.close();
11821
- cloud.close();
11843
+ await cloud.close();
11822
11844
  process.exit(1);
11823
11845
  return;
11824
11846
  }
@@ -11826,11 +11848,11 @@ syncCmd.command("pull").description("Pull cloud data to local").requiredOption("
11826
11848
  if (tables.length === 0) {
11827
11849
  console.log("No tables found to sync.");
11828
11850
  local.close();
11829
- cloud.close();
11851
+ await cloud.close();
11830
11852
  return;
11831
11853
  }
11832
11854
  console.log(`Pulling ${tables.length} table(s) from cloud...`);
11833
- const results = syncPull(local, cloud, {
11855
+ const results = await syncPull(cloud, local, {
11834
11856
  tables,
11835
11857
  onProgress: (p) => {
11836
11858
  if (p.phase === "done") {
@@ -11839,7 +11861,7 @@ syncCmd.command("pull").description("Pull cloud data to local").requiredOption("
11839
11861
  }
11840
11862
  });
11841
11863
  local.close();
11842
- cloud.close();
11864
+ await cloud.close();
11843
11865
  const totalWritten = results.reduce((s, r) => s + r.rowsWritten, 0);
11844
11866
  const totalErrors = results.reduce((s, r) => s + r.errors.length, 0);
11845
11867
  console.log(`
@@ -1 +1 @@
1
- {"version":3,"file":"cli-helpers.d.ts","sourceRoot":"","sources":["../src/cli-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWzC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,MAAM,GAClB,IAAI,CAwHN"}
1
+ {"version":3,"file":"cli-helpers.d.ts","sourceRoot":"","sources":["../src/cli-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWzC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,MAAM,GAClB,IAAI,CAqHN"}
package/dist/index.d.ts CHANGED
@@ -4,6 +4,10 @@ export { getCloudConfig, saveCloudConfig, getConnectionString, createDatabase, g
4
4
  export { syncPush, syncPull, listSqliteTables, listPgTables, type SyncOptions, type SyncResult, type SyncProgress, type SyncProgressCallback, } from "./sync.js";
5
5
  export { saveFeedback, sendFeedback, listFeedback, ensureFeedbackTable, type Feedback, } from "./feedback.js";
6
6
  export { migrateDotfile, getDataDir, getDbPath, hasLegacyDotfile, getHasnaDir, } from "./dotfile.js";
7
+ export { SyncProgressTracker, type SyncProgressInfo, type ProgressCallback, type ResumePoint, } from "./sync-progress.js";
8
+ export { detectConflicts, resolveConflicts, getWinningData, ensureConflictsTable, storeConflicts, listConflicts, resolveConflict, getConflict, purgeResolvedConflicts, type SyncConflict, type ConflictStrategy, type StoredConflict, } from "./sync-conflicts.js";
9
+ export { incrementalSyncPush, incrementalSyncPull, ensureSyncMetaTable, getSyncMetaAll, getSyncMetaForTable, resetSyncMeta, resetAllSyncMeta, type IncrementalSyncStats, type IncrementalSyncOptions, type SyncMeta, } from "./sync-incremental.js";
10
+ export { setupAutoSync, enableAutoSync, getAutoSyncConfig, type AutoSyncConfig, type AutoSyncContext, type AutoSyncResult, } from "./auto-sync.js";
7
11
  export { registerCloudTools } from "./mcp-helpers.js";
8
12
  export { registerCloudCommands } from "./cli-helpers.js";
9
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,aAAa,EACb,SAAS,EACT,cAAc,EACd,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,SAAS,GACf,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,KAAK,OAAO,GACb,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,qBAAqB,GAC3B,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,YAAY,EACZ,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,oBAAoB,GAC1B,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,KAAK,QAAQ,GACd,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,cAAc,EACd,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,WAAW,GACZ,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,aAAa,EACb,SAAS,EACT,cAAc,EACd,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,SAAS,GACf,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,KAAK,OAAO,GACb,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,qBAAqB,GAC3B,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,YAAY,EACZ,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,oBAAoB,GAC1B,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,KAAK,QAAQ,GACd,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,cAAc,EACd,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,WAAW,GACZ,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,WAAW,GACjB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,aAAa,EACb,eAAe,EACf,WAAW,EACX,sBAAsB,EACtB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,cAAc,GACpB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,QAAQ,GACd,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,cAAc,GACpB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC"}