@hasna/cloud 0.1.18 → 0.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -11643,6 +11643,59 @@ async function resolvePrimaryKeys(source, target, table, pkOption) {
11643
11643
  }
11644
11644
  return pks;
11645
11645
  }
11646
+ function pgTypeToSqlite(pgType) {
11647
+ const t = pgType.toLowerCase();
11648
+ if (t.includes("int") || t === "bigint" || t === "smallint" || t === "serial" || t === "bigserial")
11649
+ return "INTEGER";
11650
+ if (t.includes("bool"))
11651
+ return "INTEGER";
11652
+ if (t.includes("float") || t.includes("double") || t === "real" || t === "numeric" || t === "decimal")
11653
+ return "REAL";
11654
+ if (t === "bytea")
11655
+ return "BLOB";
11656
+ return "TEXT";
11657
+ }
11658
+ async function ensureTableInSqliteFromPg(target, source, table) {
11659
+ const existing = target.all(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`, table);
11660
+ if (existing.length > 0)
11661
+ return false;
11662
+ const cols = await source.all(`SELECT column_name, data_type, is_nullable, column_default
11663
+ FROM information_schema.columns
11664
+ WHERE table_schema = 'public' AND table_name = '${table}'
11665
+ ORDER BY ordinal_position`);
11666
+ if (cols.length === 0)
11667
+ return false;
11668
+ const pkCols = await source.all(`SELECT kcu.column_name
11669
+ FROM information_schema.table_constraints tc
11670
+ JOIN information_schema.key_column_usage kcu
11671
+ ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
11672
+ WHERE tc.constraint_type = 'PRIMARY KEY' AND tc.table_schema = 'public' AND tc.table_name = '${table}'
11673
+ ORDER BY kcu.ordinal_position`);
11674
+ const pkSet = new Set(pkCols.map((c) => c.column_name));
11675
+ const skipTypes = new Set(["tsvector", "tsquery", "user-defined"]);
11676
+ const filteredCols = cols.filter((c) => !skipTypes.has(c.data_type));
11677
+ const colDefs = filteredCols.map((c) => {
11678
+ const sqliteType = pgTypeToSqlite(c.data_type);
11679
+ const notNull = c.is_nullable === "NO" && !pkSet.has(c.column_name) ? " NOT NULL" : "";
11680
+ return `"${c.column_name}" ${sqliteType}${notNull}`;
11681
+ });
11682
+ if (pkSet.size > 0) {
11683
+ const pkList = [...pkSet].map((c) => `"${c}"`).join(", ");
11684
+ colDefs.push(`PRIMARY KEY (${pkList})`);
11685
+ }
11686
+ const sql = `CREATE TABLE IF NOT EXISTS "${table}" (${colDefs.join(", ")})`;
11687
+ target.exec(sql);
11688
+ process.stderr.write(` [sync] ${table}: auto-created in SQLite from PG schema
11689
+ `);
11690
+ return true;
11691
+ }
11692
+ async function ensureTablesExist(source, target, tables) {
11693
+ for (const table of tables) {
11694
+ if (!isAsyncAdapter(target) && isAsyncAdapter(source)) {
11695
+ await ensureTableInSqliteFromPg(target, source, table);
11696
+ }
11697
+ }
11698
+ }
11646
11699
  async function filterColumnsForTarget(target, table, sourceColumns) {
11647
11700
  try {
11648
11701
  if (!isAsyncAdapter(target)) {
@@ -11677,6 +11730,7 @@ async function syncTransfer(source, target, options, _direction) {
11677
11730
  } = options;
11678
11731
  const results = [];
11679
11732
  const sqliteTarget = !isAsyncAdapter(target) ? target : null;
11733
+ await ensureTablesExist(source, target, tables);
11680
11734
  if (sqliteTarget) {
11681
11735
  try {
11682
11736
  sqliteTarget.exec("PRAGMA foreign_keys = OFF");
package/dist/index.js CHANGED
@@ -9571,6 +9571,59 @@ async function resolvePrimaryKeys(source, target, table, pkOption) {
9571
9571
  }
9572
9572
  return pks;
9573
9573
  }
9574
+ function pgTypeToSqlite(pgType) {
9575
+ const t = pgType.toLowerCase();
9576
+ if (t.includes("int") || t === "bigint" || t === "smallint" || t === "serial" || t === "bigserial")
9577
+ return "INTEGER";
9578
+ if (t.includes("bool"))
9579
+ return "INTEGER";
9580
+ if (t.includes("float") || t.includes("double") || t === "real" || t === "numeric" || t === "decimal")
9581
+ return "REAL";
9582
+ if (t === "bytea")
9583
+ return "BLOB";
9584
+ return "TEXT";
9585
+ }
9586
+ async function ensureTableInSqliteFromPg(target, source, table) {
9587
+ const existing = target.all(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`, table);
9588
+ if (existing.length > 0)
9589
+ return false;
9590
+ const cols = await source.all(`SELECT column_name, data_type, is_nullable, column_default
9591
+ FROM information_schema.columns
9592
+ WHERE table_schema = 'public' AND table_name = '${table}'
9593
+ ORDER BY ordinal_position`);
9594
+ if (cols.length === 0)
9595
+ return false;
9596
+ const pkCols = await source.all(`SELECT kcu.column_name
9597
+ FROM information_schema.table_constraints tc
9598
+ JOIN information_schema.key_column_usage kcu
9599
+ ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
9600
+ WHERE tc.constraint_type = 'PRIMARY KEY' AND tc.table_schema = 'public' AND tc.table_name = '${table}'
9601
+ ORDER BY kcu.ordinal_position`);
9602
+ const pkSet = new Set(pkCols.map((c) => c.column_name));
9603
+ const skipTypes = new Set(["tsvector", "tsquery", "user-defined"]);
9604
+ const filteredCols = cols.filter((c) => !skipTypes.has(c.data_type));
9605
+ const colDefs = filteredCols.map((c) => {
9606
+ const sqliteType = pgTypeToSqlite(c.data_type);
9607
+ const notNull = c.is_nullable === "NO" && !pkSet.has(c.column_name) ? " NOT NULL" : "";
9608
+ return `"${c.column_name}" ${sqliteType}${notNull}`;
9609
+ });
9610
+ if (pkSet.size > 0) {
9611
+ const pkList = [...pkSet].map((c) => `"${c}"`).join(", ");
9612
+ colDefs.push(`PRIMARY KEY (${pkList})`);
9613
+ }
9614
+ const sql = `CREATE TABLE IF NOT EXISTS "${table}" (${colDefs.join(", ")})`;
9615
+ target.exec(sql);
9616
+ process.stderr.write(` [sync] ${table}: auto-created in SQLite from PG schema
9617
+ `);
9618
+ return true;
9619
+ }
9620
+ async function ensureTablesExist(source, target, tables) {
9621
+ for (const table of tables) {
9622
+ if (!isAsyncAdapter(target) && isAsyncAdapter(source)) {
9623
+ await ensureTableInSqliteFromPg(target, source, table);
9624
+ }
9625
+ }
9626
+ }
9574
9627
  async function filterColumnsForTarget(target, table, sourceColumns) {
9575
9628
  try {
9576
9629
  if (!isAsyncAdapter(target)) {
@@ -9605,6 +9658,7 @@ async function syncTransfer(source, target, options, _direction) {
9605
9658
  } = options;
9606
9659
  const results = [];
9607
9660
  const sqliteTarget = !isAsyncAdapter(target) ? target : null;
9661
+ await ensureTablesExist(source, target, tables);
9608
9662
  if (sqliteTarget) {
9609
9663
  try {
9610
9664
  sqliteTarget.exec("PRAGMA foreign_keys = OFF");
package/dist/mcp/index.js CHANGED
@@ -24786,6 +24786,59 @@ async function resolvePrimaryKeys(source, target, table, pkOption) {
24786
24786
  }
24787
24787
  return pks;
24788
24788
  }
24789
+ function pgTypeToSqlite(pgType) {
24790
+ const t = pgType.toLowerCase();
24791
+ if (t.includes("int") || t === "bigint" || t === "smallint" || t === "serial" || t === "bigserial")
24792
+ return "INTEGER";
24793
+ if (t.includes("bool"))
24794
+ return "INTEGER";
24795
+ if (t.includes("float") || t.includes("double") || t === "real" || t === "numeric" || t === "decimal")
24796
+ return "REAL";
24797
+ if (t === "bytea")
24798
+ return "BLOB";
24799
+ return "TEXT";
24800
+ }
24801
+ async function ensureTableInSqliteFromPg(target, source, table) {
24802
+ const existing = target.all(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`, table);
24803
+ if (existing.length > 0)
24804
+ return false;
24805
+ const cols = await source.all(`SELECT column_name, data_type, is_nullable, column_default
24806
+ FROM information_schema.columns
24807
+ WHERE table_schema = 'public' AND table_name = '${table}'
24808
+ ORDER BY ordinal_position`);
24809
+ if (cols.length === 0)
24810
+ return false;
24811
+ const pkCols = await source.all(`SELECT kcu.column_name
24812
+ FROM information_schema.table_constraints tc
24813
+ JOIN information_schema.key_column_usage kcu
24814
+ ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
24815
+ WHERE tc.constraint_type = 'PRIMARY KEY' AND tc.table_schema = 'public' AND tc.table_name = '${table}'
24816
+ ORDER BY kcu.ordinal_position`);
24817
+ const pkSet = new Set(pkCols.map((c) => c.column_name));
24818
+ const skipTypes = new Set(["tsvector", "tsquery", "user-defined"]);
24819
+ const filteredCols = cols.filter((c) => !skipTypes.has(c.data_type));
24820
+ const colDefs = filteredCols.map((c) => {
24821
+ const sqliteType = pgTypeToSqlite(c.data_type);
24822
+ const notNull = c.is_nullable === "NO" && !pkSet.has(c.column_name) ? " NOT NULL" : "";
24823
+ return `"${c.column_name}" ${sqliteType}${notNull}`;
24824
+ });
24825
+ if (pkSet.size > 0) {
24826
+ const pkList = [...pkSet].map((c) => `"${c}"`).join(", ");
24827
+ colDefs.push(`PRIMARY KEY (${pkList})`);
24828
+ }
24829
+ const sql = `CREATE TABLE IF NOT EXISTS "${table}" (${colDefs.join(", ")})`;
24830
+ target.exec(sql);
24831
+ process.stderr.write(` [sync] ${table}: auto-created in SQLite from PG schema
24832
+ `);
24833
+ return true;
24834
+ }
24835
+ async function ensureTablesExist(source, target, tables) {
24836
+ for (const table of tables) {
24837
+ if (!isAsyncAdapter(target) && isAsyncAdapter(source)) {
24838
+ await ensureTableInSqliteFromPg(target, source, table);
24839
+ }
24840
+ }
24841
+ }
24789
24842
  async function filterColumnsForTarget(target, table, sourceColumns) {
24790
24843
  try {
24791
24844
  if (!isAsyncAdapter(target)) {
@@ -24820,6 +24873,7 @@ async function syncTransfer(source, target, options, _direction) {
24820
24873
  } = options;
24821
24874
  const results = [];
24822
24875
  const sqliteTarget = !isAsyncAdapter(target) ? target : null;
24876
+ await ensureTablesExist(source, target, tables);
24823
24877
  if (sqliteTarget) {
24824
24878
  try {
24825
24879
  sqliteTarget.exec("PRAGMA foreign_keys = OFF");
@@ -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;AAqoBD;;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"}
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;AAwuBD;;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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/cloud",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
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",