@hasna/cloud 0.1.19 → 0.1.21

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 CHANGED
@@ -10967,8 +10967,21 @@ function sqliteToPostgres(sql) {
10967
10967
  out = out.replace(/\bAUTOINCREMENT\b/gi, "GENERATED ALWAYS AS IDENTITY");
10968
10968
  out = out.replace(/(?<![I])LIKE/gi, "ILIKE");
10969
10969
  out = out.replace(/\bIFNULL\s*\(/gi, "COALESCE(");
10970
+ out = out.replace(/INSERT\s+OR\s+REPLACE\s+INTO\s+"?(\w+)"?\s*\(([^)]+)\)\s*VALUES/gi, (_match, table, colList) => {
10971
+ const cols = colList.split(",").map((c) => c.trim().replace(/"/g, ""));
10972
+ const pk = cols[0];
10973
+ const updateCols = cols.slice(1);
10974
+ const setClauses = updateCols.map((c) => `"${c}" = EXCLUDED."${c}"`).join(", ");
10975
+ if (updateCols.length > 0) {
10976
+ return `INSERT INTO "${table}" (${colList}) VALUES`;
10977
+ }
10978
+ return `INSERT INTO "${table}" (${colList}) VALUES`;
10979
+ });
10970
10980
  out = out.replace(/INSERT\s+OR\s+REPLACE\s+INTO/gi, "INSERT INTO");
10971
- out = out.replace(/INSERT\s+OR\s+IGNORE\s+INTO/gi, "INSERT INTO");
10981
+ if (/INSERT\s+OR\s+IGNORE\s+INTO/i.test(out)) {
10982
+ out = out.replace(/INSERT\s+OR\s+IGNORE\s+INTO/gi, "INSERT INTO");
10983
+ out = out.replace(/;?\s*$/, " ON CONFLICT DO NOTHING");
10984
+ }
10972
10985
  return out;
10973
10986
  }
10974
10987
 
@@ -13052,6 +13065,62 @@ Done. ${results.length} services, ${totalApplied} migrations applied, ${totalErr
13052
13065
  }
13053
13066
  }
13054
13067
  });
13068
+ syncCmd.command("status").description("Show sync status for all discovered services").option("--service <name>", "Show status for a single service").option("--json", "Output as JSON").action(async (opts) => {
13069
+ const services = opts.service ? [opts.service] : discoverServices();
13070
+ const statuses = [];
13071
+ const { existsSync: existsSync9, statSync: statSync6 } = __require("fs");
13072
+ for (const service of services) {
13073
+ const dbPath = getDbPath2(service);
13074
+ const localExists = existsSync9(dbPath);
13075
+ let localSize = "\u2014";
13076
+ let tableCount = 0;
13077
+ if (localExists) {
13078
+ try {
13079
+ const stat = statSync6(dbPath);
13080
+ localSize = stat.size > 1024 * 1024 ? `${(stat.size / 1024 / 1024).toFixed(1)}MB` : `${(stat.size / 1024).toFixed(0)}KB`;
13081
+ } catch {}
13082
+ try {
13083
+ const local = new SqliteAdapter2(dbPath);
13084
+ const tables = listSqliteTables(local);
13085
+ tableCount = tables.length;
13086
+ local.close();
13087
+ } catch {}
13088
+ }
13089
+ let pgReachable = false;
13090
+ try {
13091
+ const connStr = getConnectionString(service);
13092
+ const pg2 = new PgAdapterAsync2(connStr);
13093
+ await pg2.all("SELECT 1");
13094
+ pgReachable = true;
13095
+ await pg2.close();
13096
+ } catch {}
13097
+ statuses.push({
13098
+ service,
13099
+ localDb: localExists ? dbPath : null,
13100
+ localSize,
13101
+ tables: tableCount,
13102
+ pgReachable
13103
+ });
13104
+ }
13105
+ if (opts.json) {
13106
+ console.log(JSON.stringify(statuses, null, 2));
13107
+ } else {
13108
+ const config = getCloudConfig();
13109
+ console.log(`Mode: ${config.mode}`);
13110
+ console.log(`Services: ${statuses.length}
13111
+ `);
13112
+ for (const s of statuses) {
13113
+ if (!s.localDb && !s.pgReachable)
13114
+ continue;
13115
+ const pgIcon = s.pgReachable ? "\u2713" : "\u2717";
13116
+ console.log(` ${s.service.padEnd(20)} ${s.localSize.padStart(8)} ${String(s.tables).padStart(3)} tables PG: ${pgIcon}`);
13117
+ }
13118
+ const withData = statuses.filter((s) => s.localDb);
13119
+ const pgOk = statuses.filter((s) => s.pgReachable);
13120
+ console.log(`
13121
+ ${withData.length} with local data, ${pgOk.length} with PG connection`);
13122
+ }
13123
+ });
13055
13124
  syncCmd.command("schedule").description("Manage scheduled background sync").option("--every <interval>", "Set sync interval (e.g. 5m, 10m, 1h)").option("--off", "Disable scheduled sync").option("--now", "Run a one-off sync immediately").action(async (opts) => {
13056
13125
  if (opts.off) {
13057
13126
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"dialect.d.ts","sourceRoot":"","sources":["../src/dialect.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC;AAEtC;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAGlE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,CAKpD;AAyFD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CA6BlE"}
1
+ {"version":3,"file":"dialect.d.ts","sourceRoot":"","sources":["../src/dialect.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC;AAEtC;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAGlE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,CAKpD;AA8GD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CA6BlE"}
package/dist/index.js CHANGED
@@ -4965,8 +4965,21 @@ function sqliteToPostgres(sql) {
4965
4965
  out = out.replace(/\bAUTOINCREMENT\b/gi, "GENERATED ALWAYS AS IDENTITY");
4966
4966
  out = out.replace(/(?<![I])LIKE/gi, "ILIKE");
4967
4967
  out = out.replace(/\bIFNULL\s*\(/gi, "COALESCE(");
4968
+ out = out.replace(/INSERT\s+OR\s+REPLACE\s+INTO\s+"?(\w+)"?\s*\(([^)]+)\)\s*VALUES/gi, (_match, table, colList) => {
4969
+ const cols = colList.split(",").map((c) => c.trim().replace(/"/g, ""));
4970
+ const pk = cols[0];
4971
+ const updateCols = cols.slice(1);
4972
+ const setClauses = updateCols.map((c) => `"${c}" = EXCLUDED."${c}"`).join(", ");
4973
+ if (updateCols.length > 0) {
4974
+ return `INSERT INTO "${table}" (${colList}) VALUES`;
4975
+ }
4976
+ return `INSERT INTO "${table}" (${colList}) VALUES`;
4977
+ });
4968
4978
  out = out.replace(/INSERT\s+OR\s+REPLACE\s+INTO/gi, "INSERT INTO");
4969
- out = out.replace(/INSERT\s+OR\s+IGNORE\s+INTO/gi, "INSERT INTO");
4979
+ if (/INSERT\s+OR\s+IGNORE\s+INTO/i.test(out)) {
4980
+ out = out.replace(/INSERT\s+OR\s+IGNORE\s+INTO/gi, "INSERT INTO");
4981
+ out = out.replace(/;?\s*$/, " ON CONFLICT DO NOTHING");
4982
+ }
4970
4983
  return out;
4971
4984
  }
4972
4985
  function translateDdl(ddl, dialect) {
package/dist/mcp/index.js CHANGED
@@ -24398,8 +24398,21 @@ function sqliteToPostgres(sql) {
24398
24398
  out = out.replace(/\bAUTOINCREMENT\b/gi, "GENERATED ALWAYS AS IDENTITY");
24399
24399
  out = out.replace(/(?<![I])LIKE/gi, "ILIKE");
24400
24400
  out = out.replace(/\bIFNULL\s*\(/gi, "COALESCE(");
24401
+ out = out.replace(/INSERT\s+OR\s+REPLACE\s+INTO\s+"?(\w+)"?\s*\(([^)]+)\)\s*VALUES/gi, (_match, table, colList) => {
24402
+ const cols = colList.split(",").map((c) => c.trim().replace(/"/g, ""));
24403
+ const pk = cols[0];
24404
+ const updateCols = cols.slice(1);
24405
+ const setClauses = updateCols.map((c) => `"${c}" = EXCLUDED."${c}"`).join(", ");
24406
+ if (updateCols.length > 0) {
24407
+ return `INSERT INTO "${table}" (${colList}) VALUES`;
24408
+ }
24409
+ return `INSERT INTO "${table}" (${colList}) VALUES`;
24410
+ });
24401
24411
  out = out.replace(/INSERT\s+OR\s+REPLACE\s+INTO/gi, "INSERT INTO");
24402
- out = out.replace(/INSERT\s+OR\s+IGNORE\s+INTO/gi, "INSERT INTO");
24412
+ if (/INSERT\s+OR\s+IGNORE\s+INTO/i.test(out)) {
24413
+ out = out.replace(/INSERT\s+OR\s+IGNORE\s+INTO/gi, "INSERT INTO");
24414
+ out = out.replace(/;?\s*$/, " ON CONFLICT DO NOTHING");
24415
+ }
24403
24416
  return out;
24404
24417
  }
24405
24418
 
@@ -8946,8 +8946,21 @@ function sqliteToPostgres(sql) {
8946
8946
  out = out.replace(/\bAUTOINCREMENT\b/gi, "GENERATED ALWAYS AS IDENTITY");
8947
8947
  out = out.replace(/(?<![I])LIKE/gi, "ILIKE");
8948
8948
  out = out.replace(/\bIFNULL\s*\(/gi, "COALESCE(");
8949
+ out = out.replace(/INSERT\s+OR\s+REPLACE\s+INTO\s+"?(\w+)"?\s*\(([^)]+)\)\s*VALUES/gi, (_match, table, colList) => {
8950
+ const cols = colList.split(",").map((c) => c.trim().replace(/"/g, ""));
8951
+ const pk = cols[0];
8952
+ const updateCols = cols.slice(1);
8953
+ const setClauses = updateCols.map((c) => `"${c}" = EXCLUDED."${c}"`).join(", ");
8954
+ if (updateCols.length > 0) {
8955
+ return `INSERT INTO "${table}" (${colList}) VALUES`;
8956
+ }
8957
+ return `INSERT INTO "${table}" (${colList}) VALUES`;
8958
+ });
8949
8959
  out = out.replace(/INSERT\s+OR\s+REPLACE\s+INTO/gi, "INSERT INTO");
8950
- out = out.replace(/INSERT\s+OR\s+IGNORE\s+INTO/gi, "INSERT INTO");
8960
+ if (/INSERT\s+OR\s+IGNORE\s+INTO/i.test(out)) {
8961
+ out = out.replace(/INSERT\s+OR\s+IGNORE\s+INTO/gi, "INSERT INTO");
8962
+ out = out.replace(/;?\s*$/, " ON CONFLICT DO NOTHING");
8963
+ }
8951
8964
  return out;
8952
8965
  }
8953
8966
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/cloud",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "Shared cloud infrastructure — database adapter (SQLite + PostgreSQL), sync engine, feedback system, unified dotfile config",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",