@hasna/connectors 1.3.35 → 1.3.37

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.
Files changed (49) hide show
  1. package/bin/index.js +154 -222
  2. package/bin/mcp.js +191 -268
  3. package/bin/serve.js +265 -342
  4. package/connectors/bluesky/README.md +34 -0
  5. package/connectors/bluesky/package.json +41 -0
  6. package/connectors/bluesky/src/api/client.test.ts +122 -0
  7. package/connectors/bluesky/src/api/client.ts +194 -0
  8. package/connectors/bluesky/src/api/index.ts +108 -0
  9. package/connectors/bluesky/src/index.ts +17 -0
  10. package/connectors/bluesky/src/types/index.ts +46 -0
  11. package/connectors/bluesky/tsconfig.json +16 -0
  12. package/connectors/x/src/api/media.ts +4 -3
  13. package/dashboard/dist/assets/index-ClBXkNbL.css +1 -0
  14. package/dashboard/dist/assets/index-DvfmyAO4.js +284 -0
  15. package/dashboard/dist/index.html +2 -2
  16. package/dist/.types/connectors/bluesky/src/api/client.d.ts +73 -0
  17. package/dist/.types/connectors/bluesky/src/api/index.d.ts +76 -0
  18. package/dist/.types/connectors/bluesky/src/index.d.ts +11 -0
  19. package/dist/.types/connectors/bluesky/src/types/index.d.ts +33 -0
  20. package/dist/.types/connectors/x/src/api/client.d.ts +96 -0
  21. package/dist/.types/connectors/x/src/api/index.d.ts +80 -0
  22. package/dist/.types/connectors/x/src/api/media.d.ts +54 -0
  23. package/dist/.types/connectors/x/src/api/oauth.d.ts +82 -0
  24. package/dist/.types/connectors/x/src/api/oauth1.d.ts +68 -0
  25. package/dist/.types/connectors/x/src/api/tweets.d.ts +175 -0
  26. package/dist/.types/connectors/x/src/api/users.d.ts +127 -0
  27. package/dist/.types/connectors/x/src/cli/index.d.ts +2 -0
  28. package/dist/.types/connectors/x/src/index.d.ts +6 -0
  29. package/dist/.types/connectors/x/src/types/index.d.ts +156 -0
  30. package/dist/.types/connectors/x/src/utils/config.d.ts +99 -0
  31. package/dist/.types/connectors/x/src/utils/output.d.ts +8 -0
  32. package/dist/.types/src/social/bluesky.d.ts +65 -0
  33. package/dist/.types/src/social/errors.d.ts +9 -0
  34. package/dist/.types/src/social/index.d.ts +16 -0
  35. package/dist/.types/src/social/mastodon.d.ts +32 -0
  36. package/dist/.types/src/social/types.d.ts +73 -0
  37. package/dist/.types/src/social/util.d.ts +5 -0
  38. package/dist/.types/src/social/x.d.ts +82 -0
  39. package/dist/cli/components/App.d.ts +1 -2
  40. package/dist/cli/components/CategorySelect.d.ts +1 -2
  41. package/dist/cli/components/ConnectorSelect.d.ts +1 -2
  42. package/dist/cli/components/Header.d.ts +1 -2
  43. package/dist/cli/components/InstallProgress.d.ts +1 -2
  44. package/dist/cli/components/SearchView.d.ts +1 -2
  45. package/dist/index.js +123 -110
  46. package/dist/social/index.js +1531 -0
  47. package/package.json +8 -4
  48. package/dashboard/dist/assets/index-DJjxFlTl.css +0 -1
  49. package/dashboard/dist/assets/index-DNPZ58_i.js +0 -284
package/bin/index.js CHANGED
@@ -1909,7 +1909,7 @@ var package_default;
1909
1909
  var init_package = __esm(() => {
1910
1910
  package_default = {
1911
1911
  name: "@hasna/connectors",
1912
- version: "1.3.35",
1912
+ version: "1.3.37",
1913
1913
  description: "Open source connector library - Install API connectors with a single command",
1914
1914
  type: "module",
1915
1915
  bin: {
@@ -1928,16 +1928,20 @@ var init_package = __esm(() => {
1928
1928
  ".": {
1929
1929
  import: "./dist/index.js",
1930
1930
  types: "./dist/index.d.ts"
1931
+ },
1932
+ "./social": {
1933
+ import: "./dist/social/index.js",
1934
+ types: "./dist/.types/src/social/index.d.ts"
1931
1935
  }
1932
1936
  },
1933
1937
  main: "./dist/index.js",
1934
1938
  types: "./dist/index.d.ts",
1935
1939
  scripts: {
1936
- build: "cd dashboard && bun run build && cd .. && bun build ./src/cli/index.tsx --outdir ./bin --target bun --external ink --external react --external chalk --external conf && bun build ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun build ./src/server/index.ts --outfile ./bin/serve.js --target bun && bun build ./src/index.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --outDir ./dist",
1940
+ build: "cd dashboard && bun run build && cd .. && bun build ./src/cli/index.tsx --outdir ./bin --target bun --external ink --external react --external chalk --external conf && bun build ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun build ./src/server/index.ts --outfile ./bin/serve.js --target bun && bun build ./src/index.ts --outdir ./dist --target bun && bun build ./src/social/index.ts --outfile ./dist/social/index.js --target bun && tsc --emitDeclarationOnly --outDir ./dist && tsc -p tsconfig.social.json",
1937
1941
  "build:dashboard": "cd dashboard && bun run build",
1938
1942
  postinstall: 'mkdir -p $HOME/.hasna/connectors 2>/dev/null || true; [ "$SKIP_DASHBOARD" = "1" ] || [ ! -f dashboard/package.json ] || [ -d dashboard/node_modules ] || (cd dashboard && bun install)',
1939
1943
  dev: "bun run ./src/cli/index.tsx",
1940
- typecheck: "tsc --noEmit",
1944
+ typecheck: "tsc --noEmit && tsc -p tsconfig.social.json --noEmit",
1941
1945
  test: "bun test",
1942
1946
  "sdk:build": "cd sdk && bun run build",
1943
1947
  prepublishOnly: "bun run build && bun test"
@@ -1965,7 +1969,7 @@ var init_package = __esm(() => {
1965
1969
  },
1966
1970
  dependencies: {
1967
1971
  "@hasna/cloud": "0.1.24",
1968
- "@hasna/events": "^0.1.3",
1972
+ "@hasna/events": "^0.1.7",
1969
1973
  "@modelcontextprotocol/sdk": "^1.26.0",
1970
1974
  chalk: "^5.3.0",
1971
1975
  commander: "^12.1.0",
@@ -7806,8 +7810,8 @@ __export(exports_dist, {
7806
7810
  ensureConflictsTable: () => ensureConflictsTable,
7807
7811
  ensureAllPgDatabases: () => ensureAllPgDatabases,
7808
7812
  enableAutoSync: () => enableAutoSync,
7809
- discoverSyncableServicesV2: () => discoverSyncableServices2,
7810
- discoverSyncableServices: () => discoverSyncableServices,
7813
+ discoverSyncableServicesV2: () => discoverSyncableServices,
7814
+ discoverSyncableServices: () => discoverSyncableServices2,
7811
7815
  discoverServices: () => discoverServices,
7812
7816
  detectConflicts: () => detectConflicts,
7813
7817
  createDatabase: () => createDatabase,
@@ -7833,18 +7837,18 @@ import { join as join5, relative } from "path";
7833
7837
  import { existsSync as existsSync22, mkdirSync as mkdirSync22, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
7834
7838
  import { homedir as homedir22 } from "os";
7835
7839
  import { join as join22 } from "path";
7836
- import { readdirSync as readdirSync32, existsSync as existsSync6 } from "fs";
7837
- import { join as join6 } from "path";
7838
- import { homedir as homedir5 } from "os";
7839
- import { hostname } from "os";
7840
- import { existsSync as existsSync32, readFileSync as readFileSync22 } from "fs";
7841
- import { homedir as homedir32 } from "os";
7840
+ import { readdirSync as readdirSync22, existsSync as existsSync32 } from "fs";
7842
7841
  import { join as join32 } from "path";
7843
- import { existsSync as existsSync42, readdirSync as readdirSync22 } from "fs";
7842
+ import { homedir as homedir32 } from "os";
7843
+ import { hostname } from "os";
7844
+ import { existsSync as existsSync42, readFileSync as readFileSync22 } from "fs";
7845
+ import { homedir as homedir42 } from "os";
7844
7846
  import { join as join42 } from "path";
7845
- import { join as join52, dirname as dirname2 } from "path";
7846
- import { existsSync as existsSync52, writeFileSync as writeFileSync22, unlinkSync, mkdirSync as mkdirSync32 } from "fs";
7847
- import { homedir as homedir42, platform } from "os";
7847
+ import { existsSync as existsSync52, readdirSync as readdirSync32 } from "fs";
7848
+ import { join as join52 } from "path";
7849
+ import { join as join6, dirname as dirname2 } from "path";
7850
+ import { existsSync as existsSync6, writeFileSync as writeFileSync22, unlinkSync, mkdirSync as mkdirSync32 } from "fs";
7851
+ import { homedir as homedir5, platform } from "os";
7848
7852
  function __accessProp2(key) {
7849
7853
  return this[key];
7850
7854
  }
@@ -8816,11 +8820,11 @@ function isSyncExcludedTable(table) {
8816
8820
  return SYNC_EXCLUDED_TABLE_PATTERNS.some((p) => p.test(table));
8817
8821
  }
8818
8822
  function discoverServices() {
8819
- const dataDir = join6(homedir5(), ".hasna");
8820
- if (!existsSync6(dataDir))
8823
+ const dataDir = join32(homedir32(), ".hasna");
8824
+ if (!existsSync32(dataDir))
8821
8825
  return [];
8822
8826
  try {
8823
- const entries = readdirSync32(dataDir, { withFileTypes: true });
8827
+ const entries = readdirSync22(dataDir, { withFileTypes: true });
8824
8828
  return entries.filter((e) => {
8825
8829
  if (!e.isDirectory())
8826
8830
  return false;
@@ -8832,30 +8836,30 @@ function discoverServices() {
8832
8836
  return [];
8833
8837
  }
8834
8838
  }
8835
- function discoverSyncableServices2() {
8839
+ function discoverSyncableServices() {
8836
8840
  const local = discoverServices();
8837
8841
  const pgSet = new Set(KNOWN_PG_SERVICES);
8838
8842
  return local.filter((s) => pgSet.has(s));
8839
8843
  }
8840
8844
  function getServiceDbPath(service) {
8841
- const dataDir = join6(homedir5(), ".hasna", service);
8842
- if (!existsSync6(dataDir))
8845
+ const dataDir = join32(homedir32(), ".hasna", service);
8846
+ if (!existsSync32(dataDir))
8843
8847
  return null;
8844
8848
  const candidates = [
8845
- join6(dataDir, `${service}.db`),
8846
- join6(dataDir, "data.db"),
8847
- join6(dataDir, "database.db")
8849
+ join32(dataDir, `${service}.db`),
8850
+ join32(dataDir, "data.db"),
8851
+ join32(dataDir, "database.db")
8848
8852
  ];
8849
8853
  try {
8850
- const files = readdirSync32(dataDir);
8854
+ const files = readdirSync22(dataDir);
8851
8855
  for (const f of files) {
8852
8856
  if (f.endsWith(".db") && !f.endsWith("-wal") && !f.endsWith("-shm")) {
8853
- candidates.push(join6(dataDir, f));
8857
+ candidates.push(join32(dataDir, f));
8854
8858
  }
8855
8859
  }
8856
8860
  } catch {}
8857
8861
  for (const p of candidates) {
8858
- if (existsSync6(p))
8862
+ if (existsSync32(p))
8859
8863
  return p;
8860
8864
  }
8861
8865
  return null;
@@ -9774,7 +9778,7 @@ function resetAllSyncMeta(db) {
9774
9778
  }
9775
9779
  function getAutoSyncConfig() {
9776
9780
  try {
9777
- if (!existsSync32(AUTO_SYNC_CONFIG_PATH)) {
9781
+ if (!existsSync42(AUTO_SYNC_CONFIG_PATH)) {
9778
9782
  return { ...DEFAULT_AUTO_SYNC_CONFIG };
9779
9783
  }
9780
9784
  const raw = JSON.parse(readFileSync22(AUTO_SYNC_CONFIG_PATH, "utf-8"));
@@ -9786,7 +9790,7 @@ function getAutoSyncConfig() {
9786
9790
  return { ...DEFAULT_AUTO_SYNC_CONFIG };
9787
9791
  }
9788
9792
  }
9789
- function executeAutoSync(event, local, remote, tables) {
9793
+ async function executeAutoSync(event, serviceName, local, tables) {
9790
9794
  const direction = event === "start" ? "pull" : "push";
9791
9795
  const result = {
9792
9796
  event,
@@ -9796,18 +9800,31 @@ function executeAutoSync(event, local, remote, tables) {
9796
9800
  total_rows_synced: 0,
9797
9801
  errors: []
9798
9802
  };
9803
+ let remote = null;
9799
9804
  try {
9800
- const stats = direction === "pull" ? incrementalSyncPull(remote, local, tables) : incrementalSyncPush(local, remote, tables);
9801
- for (const s of stats) {
9802
- if (s.errors.length === 0) {
9805
+ const connStr = getConnectionString(serviceName);
9806
+ remote = new PgAdapterAsync(connStr);
9807
+ const syncTables = tables.length > 0 ? tables.filter((t) => !isSyncExcludedTable(t)) : direction === "push" ? listSqliteTables(local).filter((t) => !isSyncExcludedTable(t)) : (await listPgTables(remote)).filter((t) => !isSyncExcludedTable(t));
9808
+ if (syncTables.length === 0) {
9809
+ result.success = true;
9810
+ return result;
9811
+ }
9812
+ const results = direction === "pull" ? await syncPull(remote, local, { tables: syncTables }) : await syncPush(local, remote, { tables: syncTables });
9813
+ for (const r of results) {
9814
+ if (r.errors.length === 0)
9803
9815
  result.tables_synced++;
9804
- }
9805
- result.total_rows_synced += s.synced_rows;
9806
- result.errors.push(...s.errors);
9816
+ result.total_rows_synced += r.rowsWritten;
9817
+ result.errors.push(...r.errors);
9807
9818
  }
9808
9819
  result.success = result.errors.length === 0;
9809
9820
  } catch (err) {
9810
9821
  result.errors.push(err?.message ?? String(err));
9822
+ } finally {
9823
+ if (remote) {
9824
+ try {
9825
+ await remote.close();
9826
+ } catch {}
9827
+ }
9811
9828
  }
9812
9829
  return result;
9813
9830
  }
@@ -9815,80 +9832,76 @@ function installSignalHandlers() {
9815
9832
  if (signalHandlersInstalled)
9816
9833
  return;
9817
9834
  signalHandlersInstalled = true;
9818
- const handleExit = () => {
9835
+ const handleExit = async () => {
9819
9836
  for (const fn of cleanupHandlers) {
9820
9837
  try {
9821
- fn();
9838
+ await fn();
9822
9839
  } catch {}
9823
9840
  }
9824
9841
  };
9825
- process.on("SIGTERM", () => {
9826
- handleExit();
9842
+ process.on("SIGTERM", async () => {
9843
+ await handleExit();
9827
9844
  process.exit(0);
9828
9845
  });
9829
- process.on("SIGINT", () => {
9830
- handleExit();
9846
+ process.on("SIGINT", async () => {
9847
+ await handleExit();
9831
9848
  process.exit(0);
9832
9849
  });
9833
- process.on("beforeExit", () => {
9834
- handleExit();
9850
+ process.on("beforeExit", async () => {
9851
+ await handleExit();
9835
9852
  });
9836
9853
  }
9837
9854
  function setupAutoSync(serviceName, server, local, remote, tables) {
9838
9855
  const config = getAutoSyncConfig();
9839
9856
  const cloudConfig = getCloudConfig();
9840
9857
  const isSyncEnabled = cloudConfig.mode === "hybrid" || cloudConfig.mode === "cloud";
9841
- const syncOnStart = () => {
9858
+ const syncOnStart = async () => {
9842
9859
  if (!config.auto_sync_on_start || !isSyncEnabled)
9843
9860
  return null;
9844
- return executeAutoSync("start", local, remote, tables);
9861
+ return executeAutoSync("start", serviceName, local, tables);
9845
9862
  };
9846
- const syncOnStop = () => {
9863
+ const syncOnStop = async () => {
9847
9864
  if (!config.auto_sync_on_stop || !isSyncEnabled)
9848
9865
  return null;
9849
- return executeAutoSync("stop", local, remote, tables);
9866
+ return executeAutoSync("stop", serviceName, local, tables);
9850
9867
  };
9851
9868
  if (server && typeof server.onconnect === "function") {
9852
9869
  const origOnConnect = server.onconnect;
9853
- server.onconnect = (...args) => {
9854
- syncOnStart();
9870
+ server.onconnect = async (...args) => {
9871
+ await syncOnStart();
9855
9872
  return origOnConnect.apply(server, args);
9856
9873
  };
9857
9874
  } else if (server && typeof server.on === "function") {
9858
- server.on("connect", () => {
9859
- syncOnStart();
9860
- });
9875
+ server.on("connect", () => syncOnStart());
9861
9876
  }
9862
9877
  if (server && typeof server.ondisconnect === "function") {
9863
9878
  const origOnDisconnect = server.ondisconnect;
9864
- server.ondisconnect = (...args) => {
9865
- syncOnStop();
9879
+ server.ondisconnect = async (...args) => {
9880
+ await syncOnStop();
9866
9881
  return origOnDisconnect.apply(server, args);
9867
9882
  };
9868
9883
  } else if (server && typeof server.on === "function") {
9869
- server.on("disconnect", () => {
9870
- syncOnStop();
9871
- });
9884
+ server.on("disconnect", () => syncOnStop());
9872
9885
  }
9873
9886
  installSignalHandlers();
9874
- cleanupHandlers.push(() => {
9875
- syncOnStop();
9887
+ cleanupHandlers.push(async () => {
9888
+ await syncOnStop();
9876
9889
  });
9877
9890
  return { syncOnStart, syncOnStop, config };
9878
9891
  }
9879
9892
  function enableAutoSync(serviceName, mcpServer, local, remote, tables) {
9880
9893
  setupAutoSync(serviceName, mcpServer, local, remote, tables);
9881
9894
  }
9882
- function discoverSyncableServices() {
9895
+ function discoverSyncableServices2() {
9883
9896
  const hasnaDir = getHasnaDir();
9884
9897
  const services = [];
9885
9898
  try {
9886
- const entries = readdirSync22(hasnaDir, { withFileTypes: true });
9899
+ const entries = readdirSync32(hasnaDir, { withFileTypes: true });
9887
9900
  for (const entry of entries) {
9888
9901
  if (!entry.isDirectory())
9889
9902
  continue;
9890
- const dbPath = join42(hasnaDir, entry.name, `${entry.name}.db`);
9891
- if (existsSync42(dbPath)) {
9903
+ const dbPath = join52(hasnaDir, entry.name, `${entry.name}.db`);
9904
+ if (existsSync52(dbPath)) {
9892
9905
  services.push(entry.name);
9893
9906
  }
9894
9907
  }
@@ -9899,7 +9912,7 @@ async function runScheduledSync() {
9899
9912
  const config = getCloudConfig();
9900
9913
  if (config.mode === "local")
9901
9914
  return [];
9902
- const services = discoverSyncableServices();
9915
+ const services = discoverSyncableServices2();
9903
9916
  const results = [];
9904
9917
  let remote = null;
9905
9918
  for (const service of services) {
@@ -9910,8 +9923,8 @@ async function runScheduledSync() {
9910
9923
  errors: []
9911
9924
  };
9912
9925
  try {
9913
- const dbPath = join42(getDataDir(service), `${service}.db`);
9914
- if (!existsSync42(dbPath)) {
9926
+ const dbPath = join52(getDataDir(service), `${service}.db`);
9927
+ if (!existsSync52(dbPath)) {
9915
9928
  continue;
9916
9929
  }
9917
9930
  const local = new SqliteAdapter(dbPath);
@@ -9992,34 +10005,34 @@ function minutesToCron(minutes) {
9992
10005
  }
9993
10006
  function getWorkerPath() {
9994
10007
  const dir = typeof import.meta.dir === "string" ? import.meta.dir : dirname2(import.meta.url.replace("file://", ""));
9995
- const tsPath = join52(dir, "scheduled-sync.ts");
9996
- const jsPath = join52(dir, "scheduled-sync.js");
10008
+ const tsPath = join6(dir, "scheduled-sync.ts");
10009
+ const jsPath = join6(dir, "scheduled-sync.js");
9997
10010
  try {
9998
- if (existsSync52(tsPath))
10011
+ if (existsSync6(tsPath))
9999
10012
  return tsPath;
10000
10013
  } catch {}
10001
10014
  return jsPath;
10002
10015
  }
10003
10016
  function getBunPath() {
10004
10017
  const candidates = [
10005
- join52(homedir42(), ".bun", "bin", "bun"),
10018
+ join6(homedir5(), ".bun", "bin", "bun"),
10006
10019
  "/usr/local/bin/bun",
10007
10020
  "/usr/bin/bun"
10008
10021
  ];
10009
10022
  for (const p of candidates) {
10010
- if (existsSync52(p))
10023
+ if (existsSync6(p))
10011
10024
  return p;
10012
10025
  }
10013
10026
  return "bun";
10014
10027
  }
10015
10028
  function getLaunchdPlistPath() {
10016
- return join52(homedir42(), "Library", "LaunchAgents", `com.hasna.cloud-sync.plist`);
10029
+ return join6(homedir5(), "Library", "LaunchAgents", `com.hasna.cloud-sync.plist`);
10017
10030
  }
10018
10031
  function createLaunchdPlist(intervalMinutes) {
10019
10032
  const workerPath = getWorkerPath();
10020
10033
  const bunPath = getBunPath();
10021
- const logPath = join52(CONFIG_DIR2, "sync.log");
10022
- const errorLogPath = join52(CONFIG_DIR2, "sync-error.log");
10034
+ const logPath = join6(CONFIG_DIR2, "sync.log");
10035
+ const errorLogPath = join6(CONFIG_DIR2, "sync-error.log");
10023
10036
  return `<?xml version="1.0" encoding="UTF-8"?>
10024
10037
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
10025
10038
  <plist version="1.0">
@@ -10045,7 +10058,7 @@ function createLaunchdPlist(intervalMinutes) {
10045
10058
  <key>PATH</key>
10046
10059
  <string>${process.env.PATH || "/usr/local/bin:/usr/bin:/bin"}</string>
10047
10060
  <key>HOME</key>
10048
- <string>${homedir42()}</string>
10061
+ <string>${homedir5()}</string>
10049
10062
  </dict>
10050
10063
  </dict>
10051
10064
  </plist>`;
@@ -10070,7 +10083,7 @@ async function removeLaunchd() {
10070
10083
  } catch {}
10071
10084
  }
10072
10085
  function getSystemdDir() {
10073
- return join52(homedir42(), ".config", "systemd", "user");
10086
+ return join6(homedir5(), ".config", "systemd", "user");
10074
10087
  }
10075
10088
  function createSystemdService() {
10076
10089
  const workerPath = getWorkerPath();
@@ -10082,7 +10095,7 @@ After=network.target
10082
10095
  [Service]
10083
10096
  Type=oneshot
10084
10097
  ExecStart=${bunPath} run ${workerPath}
10085
- Environment=HOME=${homedir42()}
10098
+ Environment=HOME=${homedir5()}
10086
10099
  Environment=PATH=${process.env.PATH || "/usr/local/bin:/usr/bin:/bin"}
10087
10100
 
10088
10101
  [Install]
@@ -10105,8 +10118,8 @@ WantedBy=timers.target
10105
10118
  async function registerSystemd(intervalMinutes) {
10106
10119
  const dir = getSystemdDir();
10107
10120
  mkdirSync32(dir, { recursive: true });
10108
- writeFileSync22(join52(dir, `${SERVICE_NAME}.service`), createSystemdService());
10109
- writeFileSync22(join52(dir, `${SERVICE_NAME}.timer`), createSystemdTimer(intervalMinutes));
10121
+ writeFileSync22(join6(dir, `${SERVICE_NAME}.service`), createSystemdService());
10122
+ writeFileSync22(join6(dir, `${SERVICE_NAME}.timer`), createSystemdTimer(intervalMinutes));
10110
10123
  await Bun.spawn(["systemctl", "--user", "daemon-reload"]).exited;
10111
10124
  await Bun.spawn(["systemctl", "--user", "enable", "--now", `${SERVICE_NAME}.timer`]).exited;
10112
10125
  }
@@ -10116,10 +10129,10 @@ async function removeSystemd() {
10116
10129
  } catch {}
10117
10130
  const dir = getSystemdDir();
10118
10131
  try {
10119
- unlinkSync(join52(dir, `${SERVICE_NAME}.service`));
10132
+ unlinkSync(join6(dir, `${SERVICE_NAME}.service`));
10120
10133
  } catch {}
10121
10134
  try {
10122
- unlinkSync(join52(dir, `${SERVICE_NAME}.timer`));
10135
+ unlinkSync(join6(dir, `${SERVICE_NAME}.timer`));
10123
10136
  } catch {}
10124
10137
  try {
10125
10138
  await Bun.spawn(["systemctl", "--user", "daemon-reload"]).exited;
@@ -10156,9 +10169,9 @@ function getSyncScheduleStatus() {
10156
10169
  let mechanism = "none";
10157
10170
  if (registered) {
10158
10171
  if (platform() === "darwin") {
10159
- mechanism = existsSync52(getLaunchdPlistPath()) ? "launchd" : "none";
10172
+ mechanism = existsSync6(getLaunchdPlistPath()) ? "launchd" : "none";
10160
10173
  } else {
10161
- mechanism = existsSync52(join52(getSystemdDir(), `${SERVICE_NAME}.timer`)) ? "systemd" : "none";
10174
+ mechanism = existsSync6(join6(getSystemdDir(), `${SERVICE_NAME}.timer`)) ? "systemd" : "none";
10162
10175
  }
10163
10176
  }
10164
10177
  return {
@@ -18741,7 +18754,7 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
18741
18754
  __export2(exports_discover, {
18742
18755
  isSyncExcludedTable: () => isSyncExcludedTable,
18743
18756
  getServiceDbPath: () => getServiceDbPath,
18744
- discoverSyncableServices: () => discoverSyncableServices2,
18757
+ discoverSyncableServices: () => discoverSyncableServices,
18745
18758
  discoverServices: () => discoverServices,
18746
18759
  SYNC_EXCLUDED_TABLE_PATTERNS: () => SYNC_EXCLUDED_TABLE_PATTERNS,
18747
18760
  KNOWN_PG_SERVICES: () => KNOWN_PG_SERVICES
@@ -18796,8 +18809,10 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
18796
18809
  init_config();
18797
18810
  init_config();
18798
18811
  init_dotfile();
18812
+ init_adapter();
18799
18813
  init_config();
18800
- AUTO_SYNC_CONFIG_PATH = join32(homedir32(), ".hasna", "cloud", "config.json");
18814
+ init_discover();
18815
+ AUTO_SYNC_CONFIG_PATH = join42(homedir42(), ".hasna", "cloud", "config.json");
18801
18816
  DEFAULT_AUTO_SYNC_CONFIG = {
18802
18817
  auto_sync_on_start: true,
18803
18818
  auto_sync_on_stop: true
@@ -18807,7 +18822,7 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
18807
18822
  init_adapter();
18808
18823
  init_dotfile();
18809
18824
  init_config();
18810
- CONFIG_DIR2 = join52(homedir42(), ".hasna", "cloud");
18825
+ CONFIG_DIR2 = join6(homedir5(), ".hasna", "cloud");
18811
18826
  init_adapter();
18812
18827
  init_config();
18813
18828
  init_discover();
@@ -27180,6 +27195,13 @@ var init_social_media = __esm(() => {
27180
27195
  category: "Social Media",
27181
27196
  tags: ["social", "fediverse", "decentralized"]
27182
27197
  },
27198
+ {
27199
+ name: "bluesky",
27200
+ displayName: "Bluesky",
27201
+ description: "AT Protocol social network - posts, threads, mentions",
27202
+ category: "Social Media",
27203
+ tags: ["social", "atproto", "decentralized"]
27204
+ },
27183
27205
  {
27184
27206
  name: "brandblast",
27185
27207
  displayName: "BrandBlast",
@@ -35628,7 +35650,7 @@ var init_types3 = __esm(() => {
35628
35650
  ProgressTokenSchema = union([string2(), number2().int()]);
35629
35651
  CursorSchema = string2();
35630
35652
  TaskCreationParamsSchema = looseObject({
35631
- ttl: number2().optional(),
35653
+ ttl: union([number2(), _null3()]).optional(),
35632
35654
  pollInterval: number2().optional()
35633
35655
  });
35634
35656
  TaskMetadataSchema = object({
@@ -35776,8 +35798,7 @@ var init_types3 = __esm(() => {
35776
35798
  roots: object({
35777
35799
  listChanged: boolean2().optional()
35778
35800
  }).optional(),
35779
- tasks: ClientTasksCapabilitySchema.optional(),
35780
- extensions: record(string2(), AssertObjectSchema).optional()
35801
+ tasks: ClientTasksCapabilitySchema.optional()
35781
35802
  });
35782
35803
  InitializeRequestParamsSchema = BaseRequestParamsSchema.extend({
35783
35804
  protocolVersion: string2(),
@@ -35802,8 +35823,7 @@ var init_types3 = __esm(() => {
35802
35823
  tools: object({
35803
35824
  listChanged: boolean2().optional()
35804
35825
  }).optional(),
35805
- tasks: ServerTasksCapabilitySchema.optional(),
35806
- extensions: record(string2(), AssertObjectSchema).optional()
35826
+ tasks: ServerTasksCapabilitySchema.optional()
35807
35827
  });
35808
35828
  InitializeResultSchema = ResultSchema.extend({
35809
35829
  protocolVersion: string2(),
@@ -35918,7 +35938,6 @@ var init_types3 = __esm(() => {
35918
35938
  uri: string2(),
35919
35939
  description: optional(string2()),
35920
35940
  mimeType: optional(string2()),
35921
- size: optional(number2()),
35922
35941
  annotations: AnnotationsSchema.optional(),
35923
35942
  _meta: optional(looseObject({}))
35924
35943
  });
@@ -42522,9 +42541,6 @@ var require_data = __commonJS((exports, module) => {
42522
42541
  var require_utils3 = __commonJS((exports, module) => {
42523
42542
  var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
42524
42543
  var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
42525
- var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
42526
- var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
42527
- var isPathCharacter = RegExp.prototype.test.bind(/^[\da-z\-._~!$&'()*+,;=:@/]$/iu);
42528
42544
  function stringArrayToHexStripped(input) {
42529
42545
  let acc = "";
42530
42546
  let code = 0;
@@ -42718,77 +42734,27 @@ var require_utils3 = __commonJS((exports, module) => {
42718
42734
  }
42719
42735
  return output.join("");
42720
42736
  }
42721
- var HOST_DELIMS = { "@": "%40", "/": "%2F", "?": "%3F", "#": "%23", ":": "%3A" };
42722
- var HOST_DELIM_RE = /[@/?#:]/g;
42723
- var HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
42724
- function reescapeHostDelimiters(host, isIP) {
42725
- const re = isIP ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
42726
- re.lastIndex = 0;
42727
- return host.replace(re, (ch) => HOST_DELIMS[ch]);
42728
- }
42729
- function normalizePercentEncoding(input, decodeUnreserved = false) {
42730
- if (input.indexOf("%") === -1) {
42731
- return input;
42737
+ function normalizeComponentEncoding(component, esc2) {
42738
+ const func = esc2 !== true ? escape : unescape;
42739
+ if (component.scheme !== undefined) {
42740
+ component.scheme = func(component.scheme);
42732
42741
  }
42733
- let output = "";
42734
- for (let i = 0;i < input.length; i++) {
42735
- if (input[i] === "%" && i + 2 < input.length) {
42736
- const hex = input.slice(i + 1, i + 3);
42737
- if (isHexPair(hex)) {
42738
- const normalizedHex = hex.toUpperCase();
42739
- const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
42740
- if (decodeUnreserved && isUnreserved(decoded)) {
42741
- output += decoded;
42742
- } else {
42743
- output += "%" + normalizedHex;
42744
- }
42745
- i += 2;
42746
- continue;
42747
- }
42748
- }
42749
- output += input[i];
42742
+ if (component.userinfo !== undefined) {
42743
+ component.userinfo = func(component.userinfo);
42750
42744
  }
42751
- return output;
42752
- }
42753
- function normalizePathEncoding(input) {
42754
- let output = "";
42755
- for (let i = 0;i < input.length; i++) {
42756
- if (input[i] === "%" && i + 2 < input.length) {
42757
- const hex = input.slice(i + 1, i + 3);
42758
- if (isHexPair(hex)) {
42759
- const normalizedHex = hex.toUpperCase();
42760
- const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
42761
- if (decoded !== "." && isUnreserved(decoded)) {
42762
- output += decoded;
42763
- } else {
42764
- output += "%" + normalizedHex;
42765
- }
42766
- i += 2;
42767
- continue;
42768
- }
42769
- }
42770
- if (isPathCharacter(input[i])) {
42771
- output += input[i];
42772
- } else {
42773
- output += escape(input[i]);
42774
- }
42745
+ if (component.host !== undefined) {
42746
+ component.host = func(component.host);
42775
42747
  }
42776
- return output;
42777
- }
42778
- function escapePreservingEscapes(input) {
42779
- let output = "";
42780
- for (let i = 0;i < input.length; i++) {
42781
- if (input[i] === "%" && i + 2 < input.length) {
42782
- const hex = input.slice(i + 1, i + 3);
42783
- if (isHexPair(hex)) {
42784
- output += "%" + hex.toUpperCase();
42785
- i += 2;
42786
- continue;
42787
- }
42788
- }
42789
- output += escape(input[i]);
42748
+ if (component.path !== undefined) {
42749
+ component.path = func(component.path);
42790
42750
  }
42791
- return output;
42751
+ if (component.query !== undefined) {
42752
+ component.query = func(component.query);
42753
+ }
42754
+ if (component.fragment !== undefined) {
42755
+ component.fragment = func(component.fragment);
42756
+ }
42757
+ return component;
42792
42758
  }
42793
42759
  function recomposeAuthority(component) {
42794
42760
  const uriTokens = [];
@@ -42803,7 +42769,7 @@ var require_utils3 = __commonJS((exports, module) => {
42803
42769
  if (ipV6res.isIPV6 === true) {
42804
42770
  host = `[${ipV6res.escapedHost}]`;
42805
42771
  } else {
42806
- host = reescapeHostDelimiters(host, false);
42772
+ host = component.host;
42807
42773
  }
42808
42774
  }
42809
42775
  uriTokens.push(host);
@@ -42817,10 +42783,7 @@ var require_utils3 = __commonJS((exports, module) => {
42817
42783
  module.exports = {
42818
42784
  nonSimpleDomain,
42819
42785
  recomposeAuthority,
42820
- reescapeHostDelimiters,
42821
- normalizePercentEncoding,
42822
- normalizePathEncoding,
42823
- escapePreservingEscapes,
42786
+ normalizeComponentEncoding,
42824
42787
  removeDotSegments,
42825
42788
  isIPv4,
42826
42789
  isUUID,
@@ -43005,11 +42968,11 @@ var require_schemes = __commonJS((exports, module) => {
43005
42968
 
43006
42969
  // node_modules/fast-uri/index.js
43007
42970
  var require_fast_uri = __commonJS((exports, module) => {
43008
- var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils3();
42971
+ var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizeComponentEncoding, isIPv4, nonSimpleDomain } = require_utils3();
43009
42972
  var { SCHEMES, getSchemeHandler } = require_schemes();
43010
42973
  function normalize(uri, options) {
43011
42974
  if (typeof uri === "string") {
43012
- uri = normalizeString(uri, options);
42975
+ uri = serialize(parse6(uri, options), options);
43013
42976
  } else if (typeof uri === "object") {
43014
42977
  uri = parse6(serialize(uri, options), options);
43015
42978
  }
@@ -43075,9 +43038,19 @@ var require_fast_uri = __commonJS((exports, module) => {
43075
43038
  return target;
43076
43039
  }
43077
43040
  function equal(uriA, uriB, options) {
43078
- const normalizedA = normalizeComparableURI(uriA, options);
43079
- const normalizedB = normalizeComparableURI(uriB, options);
43080
- return normalizedA !== undefined && normalizedB !== undefined && normalizedA.toLowerCase() === normalizedB.toLowerCase();
43041
+ if (typeof uriA === "string") {
43042
+ uriA = unescape(uriA);
43043
+ uriA = serialize(normalizeComponentEncoding(parse6(uriA, options), true), { ...options, skipEscape: true });
43044
+ } else if (typeof uriA === "object") {
43045
+ uriA = serialize(normalizeComponentEncoding(uriA, true), { ...options, skipEscape: true });
43046
+ }
43047
+ if (typeof uriB === "string") {
43048
+ uriB = unescape(uriB);
43049
+ uriB = serialize(normalizeComponentEncoding(parse6(uriB, options), true), { ...options, skipEscape: true });
43050
+ } else if (typeof uriB === "object") {
43051
+ uriB = serialize(normalizeComponentEncoding(uriB, true), { ...options, skipEscape: true });
43052
+ }
43053
+ return uriA.toLowerCase() === uriB.toLowerCase();
43081
43054
  }
43082
43055
  function serialize(cmpts, opts) {
43083
43056
  const component = {
@@ -43103,12 +43076,12 @@ var require_fast_uri = __commonJS((exports, module) => {
43103
43076
  schemeHandler.serialize(component, options);
43104
43077
  if (component.path !== undefined) {
43105
43078
  if (!options.skipEscape) {
43106
- component.path = escapePreservingEscapes(component.path);
43079
+ component.path = escape(component.path);
43107
43080
  if (component.scheme !== undefined) {
43108
43081
  component.path = component.path.split("%3A").join(":");
43109
43082
  }
43110
43083
  } else {
43111
- component.path = normalizePercentEncoding(component.path);
43084
+ component.path = unescape(component.path);
43112
43085
  }
43113
43086
  }
43114
43087
  if (options.reference !== "suffix" && component.scheme) {
@@ -43143,16 +43116,7 @@ var require_fast_uri = __commonJS((exports, module) => {
43143
43116
  return uriTokens.join("");
43144
43117
  }
43145
43118
  var URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
43146
- function getParseError(parsed, matches) {
43147
- if (matches[2] !== undefined && parsed.path && parsed.path[0] !== "/") {
43148
- return 'URI path must start with "/" when authority is present.';
43149
- }
43150
- if (typeof parsed.port === "number" && (parsed.port < 0 || parsed.port > 65535)) {
43151
- return "URI port is malformed.";
43152
- }
43153
- return;
43154
- }
43155
- function parseWithStatus(uri, opts) {
43119
+ function parse6(uri, opts) {
43156
43120
  const options = Object.assign({}, opts);
43157
43121
  const parsed = {
43158
43122
  scheme: undefined,
@@ -43163,7 +43127,6 @@ var require_fast_uri = __commonJS((exports, module) => {
43163
43127
  query: undefined,
43164
43128
  fragment: undefined
43165
43129
  };
43166
- let malformedAuthorityOrPort = false;
43167
43130
  let isIP = false;
43168
43131
  if (options.reference === "suffix") {
43169
43132
  if (options.scheme) {
@@ -43184,11 +43147,6 @@ var require_fast_uri = __commonJS((exports, module) => {
43184
43147
  if (isNaN(parsed.port)) {
43185
43148
  parsed.port = matches[5];
43186
43149
  }
43187
- const parseError = getParseError(parsed, matches);
43188
- if (parseError !== undefined) {
43189
- parsed.error = parsed.error || parseError;
43190
- malformedAuthorityOrPort = true;
43191
- }
43192
43150
  if (parsed.host) {
43193
43151
  const ipv4result = isIPv4(parsed.host);
43194
43152
  if (ipv4result === false) {
@@ -43227,18 +43185,14 @@ var require_fast_uri = __commonJS((exports, module) => {
43227
43185
  parsed.scheme = unescape(parsed.scheme);
43228
43186
  }
43229
43187
  if (parsed.host !== undefined) {
43230
- parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
43188
+ parsed.host = unescape(parsed.host);
43231
43189
  }
43232
43190
  }
43233
43191
  if (parsed.path) {
43234
- parsed.path = normalizePathEncoding(parsed.path);
43192
+ parsed.path = escape(unescape(parsed.path));
43235
43193
  }
43236
43194
  if (parsed.fragment) {
43237
- try {
43238
- parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
43239
- } catch {
43240
- parsed.error = parsed.error || "URI malformed";
43241
- }
43195
+ parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
43242
43196
  }
43243
43197
  }
43244
43198
  if (schemeHandler && schemeHandler.parse) {
@@ -43247,29 +43201,7 @@ var require_fast_uri = __commonJS((exports, module) => {
43247
43201
  } else {
43248
43202
  parsed.error = parsed.error || "URI can not be parsed.";
43249
43203
  }
43250
- return { parsed, malformedAuthorityOrPort };
43251
- }
43252
- function parse6(uri, opts) {
43253
- return parseWithStatus(uri, opts).parsed;
43254
- }
43255
- function normalizeString(uri, opts) {
43256
- return normalizeStringWithStatus(uri, opts).normalized;
43257
- }
43258
- function normalizeStringWithStatus(uri, opts) {
43259
- const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
43260
- return {
43261
- normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
43262
- malformedAuthorityOrPort
43263
- };
43264
- }
43265
- function normalizeComparableURI(uri, opts) {
43266
- if (typeof uri === "string") {
43267
- const { normalized, malformedAuthorityOrPort } = normalizeStringWithStatus(uri, opts);
43268
- return malformedAuthorityOrPort ? undefined : normalized;
43269
- }
43270
- if (typeof uri === "object") {
43271
- return serialize(uri, opts);
43272
- }
43204
+ return parsed;
43273
43205
  }
43274
43206
  var fastUri = {
43275
43207
  SCHEMES,
@@ -43404,7 +43336,7 @@ var require_core = __commonJS((exports) => {
43404
43336
  constructor(opts = {}) {
43405
43337
  this.schemas = {};
43406
43338
  this.refs = {};
43407
- this.formats = Object.create(null);
43339
+ this.formats = {};
43408
43340
  this._compilations = new Set;
43409
43341
  this._loading = {};
43410
43342
  this._cache = new Map;