@hasna/connectors 1.3.7 → 1.3.8

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/bin/serve.js CHANGED
@@ -23,12 +23,34 @@ __export(exports_database, {
23
23
  shortUuid: () => shortUuid,
24
24
  now: () => now,
25
25
  getDatabase: () => getDatabase,
26
+ getConnectorsHome: () => getConnectorsHome,
26
27
  closeDatabase: () => closeDatabase
27
28
  });
28
29
  import { Database } from "bun:sqlite";
29
30
  import { join } from "path";
30
31
  import { homedir } from "os";
31
- import { mkdirSync } from "fs";
32
+ import { mkdirSync, existsSync, readdirSync, copyFileSync, statSync } from "fs";
33
+ function getConnectorsHome() {
34
+ const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir();
35
+ const newDir = join(home, ".hasna", "connectors");
36
+ const oldDir = join(home, ".connectors");
37
+ if (existsSync(oldDir) && !existsSync(newDir)) {
38
+ mkdirSync(newDir, { recursive: true });
39
+ try {
40
+ for (const file of readdirSync(oldDir)) {
41
+ const oldPath = join(oldDir, file);
42
+ const newPath = join(newDir, file);
43
+ try {
44
+ if (statSync(oldPath).isFile()) {
45
+ copyFileSync(oldPath, newPath);
46
+ }
47
+ } catch {}
48
+ }
49
+ } catch {}
50
+ }
51
+ mkdirSync(newDir, { recursive: true });
52
+ return newDir;
53
+ }
32
54
  function getDatabase(path) {
33
55
  if (_db)
34
56
  return _db;
@@ -143,20 +165,19 @@ function migrate(db) {
143
165
  }
144
166
  var DB_DIR, DB_PATH, _db = null;
145
167
  var init_database = __esm(() => {
146
- DB_DIR = join(homedir(), ".connectors");
168
+ DB_DIR = getConnectorsHome();
147
169
  DB_PATH = join(DB_DIR, "connectors.db");
148
170
  });
149
171
 
150
172
  // src/lib/llm.ts
151
- import { existsSync, readFileSync, writeFileSync, mkdirSync as mkdirSync2 } from "fs";
173
+ import { existsSync as existsSync2, readFileSync, writeFileSync, mkdirSync as mkdirSync2 } from "fs";
152
174
  import { join as join2 } from "path";
153
- import { homedir as homedir2 } from "os";
154
175
  function getLlmConfigPath() {
155
- return join2(homedir2(), ".connectors", "llm.json");
176
+ return join2(getConnectorsHome(), "llm.json");
156
177
  }
157
178
  function getLlmConfig() {
158
179
  const path = getLlmConfigPath();
159
- if (!existsSync(path))
180
+ if (!existsSync2(path))
160
181
  return null;
161
182
  try {
162
183
  return JSON.parse(readFileSync(path, "utf-8"));
@@ -165,7 +186,7 @@ function getLlmConfig() {
165
186
  }
166
187
  }
167
188
  function saveLlmConfig(config) {
168
- const dir = join2(homedir2(), ".connectors");
189
+ const dir = getConnectorsHome();
169
190
  mkdirSync2(dir, { recursive: true });
170
191
  writeFileSync(getLlmConfigPath(), JSON.stringify(config, null, 2));
171
192
  }
@@ -252,6 +273,7 @@ class LLMClient {
252
273
  }
253
274
  var PROVIDER_BASE_URLS;
254
275
  var init_llm = __esm(() => {
276
+ init_database();
255
277
  PROVIDER_BASE_URLS = {
256
278
  cerebras: "https://api.cerebras.ai/v1",
257
279
  groq: "https://api.groq.com/openai/v1",
@@ -558,7 +580,7 @@ var init_promotions = __esm(() => {
558
580
  });
559
581
 
560
582
  // src/server/serve.ts
561
- import { existsSync as existsSync6, readdirSync as readdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync6 } from "fs";
583
+ import { existsSync as existsSync7, readdirSync as readdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync6 } from "fs";
562
584
 
563
585
  // src/db/agents.ts
564
586
  init_database();
@@ -787,12 +809,12 @@ async function runWorkflow(workflow) {
787
809
  }
788
810
 
789
811
  // src/server/serve.ts
812
+ init_database();
790
813
  import { join as join7, dirname as dirname3, extname, basename } from "path";
791
814
  import { fileURLToPath as fileURLToPath3 } from "url";
792
- import { homedir as homedir6 } from "os";
793
815
 
794
816
  // src/lib/registry.ts
795
- import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
817
+ import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
796
818
  import { join as join3, dirname } from "path";
797
819
  import { fileURLToPath } from "url";
798
820
  var CONNECTORS = [
@@ -1181,6 +1203,13 @@ var CONNECTORS = [
1181
1203
  category: "Data & Analytics",
1182
1204
  tags: ["weather", "data"]
1183
1205
  },
1206
+ {
1207
+ name: "arxiv",
1208
+ displayName: "arXiv",
1209
+ description: "Research paper search and retrieval",
1210
+ category: "Data & Analytics",
1211
+ tags: ["research", "papers", "academic"]
1212
+ },
1184
1213
  {
1185
1214
  name: "brandsight",
1186
1215
  displayName: "Brandsight",
@@ -6704,13 +6733,13 @@ function loadConnectorVersions() {
6704
6733
  join3(thisDir, "..", "connectors"),
6705
6734
  join3(thisDir, "..", "..", "connectors")
6706
6735
  ];
6707
- const connectorsDir = candidates.find((d) => existsSync2(d));
6736
+ const connectorsDir = candidates.find((d) => existsSync3(d));
6708
6737
  if (!connectorsDir)
6709
6738
  return;
6710
6739
  for (const connector of CONNECTORS) {
6711
6740
  try {
6712
6741
  const pkgPath = join3(connectorsDir, `connect-${connector.name}`, "package.json");
6713
- if (existsSync2(pkgPath)) {
6742
+ if (existsSync3(pkgPath)) {
6714
6743
  const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
6715
6744
  connector.version = pkg.version || "0.0.0";
6716
6745
  }
@@ -6719,17 +6748,17 @@ function loadConnectorVersions() {
6719
6748
  }
6720
6749
 
6721
6750
  // src/lib/installer.ts
6722
- import { existsSync as existsSync3, cpSync, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2, readdirSync, statSync, rmSync } from "fs";
6723
- import { homedir as homedir3 } from "os";
6751
+ init_database();
6752
+ import { existsSync as existsSync4, cpSync, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2, readdirSync as readdirSync2, statSync as statSync2, rmSync } from "fs";
6724
6753
  import { join as join4, dirname as dirname2 } from "path";
6725
6754
  import { fileURLToPath as fileURLToPath2 } from "url";
6726
6755
  var __dirname2 = dirname2(fileURLToPath2(import.meta.url));
6727
6756
  function resolveConnectorsDir() {
6728
6757
  const fromBin = join4(__dirname2, "..", "connectors");
6729
- if (existsSync3(fromBin))
6758
+ if (existsSync4(fromBin))
6730
6759
  return fromBin;
6731
6760
  const fromSrc = join4(__dirname2, "..", "..", "connectors");
6732
- if (existsSync3(fromSrc))
6761
+ if (existsSync4(fromSrc))
6733
6762
  return fromSrc;
6734
6763
  return fromBin;
6735
6764
  }
@@ -6751,14 +6780,14 @@ function installConnector(name, options = {}) {
6751
6780
  const sourcePath = getConnectorPath(name);
6752
6781
  const destDir = join4(targetDir, ".connectors");
6753
6782
  const destPath = join4(destDir, connectorName);
6754
- if (!existsSync3(sourcePath)) {
6783
+ if (!existsSync4(sourcePath)) {
6755
6784
  return {
6756
6785
  connector: name,
6757
6786
  success: false,
6758
6787
  error: `Connector '${name}' not found`
6759
6788
  };
6760
6789
  }
6761
- if (existsSync3(destPath) && !overwrite) {
6790
+ if (existsSync4(destPath) && !overwrite) {
6762
6791
  return {
6763
6792
  connector: name,
6764
6793
  success: false,
@@ -6767,21 +6796,21 @@ function installConnector(name, options = {}) {
6767
6796
  };
6768
6797
  }
6769
6798
  try {
6770
- if (!existsSync3(destDir)) {
6799
+ if (!existsSync4(destDir)) {
6771
6800
  mkdirSync3(destDir, { recursive: true });
6772
6801
  }
6773
6802
  cpSync(sourcePath, destPath, { recursive: true });
6774
- const homeCredDir = join4(homedir3(), ".connectors", connectorName);
6775
- if (existsSync3(homeCredDir)) {
6803
+ const homeCredDir = join4(getConnectorsHome(), connectorName);
6804
+ if (existsSync4(homeCredDir)) {
6776
6805
  const filesToCopy = ["credentials.json", "current_profile"];
6777
6806
  for (const file of filesToCopy) {
6778
6807
  const src = join4(homeCredDir, file);
6779
- if (existsSync3(src)) {
6808
+ if (existsSync4(src)) {
6780
6809
  cpSync(src, join4(destPath, file));
6781
6810
  }
6782
6811
  }
6783
6812
  const profilesDir = join4(homeCredDir, "profiles");
6784
- if (existsSync3(profilesDir)) {
6813
+ if (existsSync4(profilesDir)) {
6785
6814
  cpSync(profilesDir, join4(destPath, "profiles"), { recursive: true });
6786
6815
  }
6787
6816
  }
@@ -6801,7 +6830,7 @@ function installConnector(name, options = {}) {
6801
6830
  }
6802
6831
  function updateConnectorsIndex(connectorsDir) {
6803
6832
  const indexPath = join4(connectorsDir, "index.ts");
6804
- const connectors = readdirSync(connectorsDir).filter((f) => f.startsWith("connect-") && !f.includes("."));
6833
+ const connectors = readdirSync2(connectorsDir).filter((f) => f.startsWith("connect-") && !f.includes("."));
6805
6834
  const exports = connectors.map((c) => {
6806
6835
  const name = c.replace("connect-", "");
6807
6836
  return `export * as ${name} from './${c}/src/index.js';`;
@@ -6818,18 +6847,18 @@ ${exports}
6818
6847
  }
6819
6848
  function getInstalledConnectors(targetDir = process.cwd()) {
6820
6849
  const connectorsDir = join4(targetDir, ".connectors");
6821
- if (!existsSync3(connectorsDir)) {
6850
+ if (!existsSync4(connectorsDir)) {
6822
6851
  return [];
6823
6852
  }
6824
- return readdirSync(connectorsDir).filter((f) => {
6853
+ return readdirSync2(connectorsDir).filter((f) => {
6825
6854
  const fullPath = join4(connectorsDir, f);
6826
- return f.startsWith("connect-") && statSync(fullPath).isDirectory();
6855
+ return f.startsWith("connect-") && statSync2(fullPath).isDirectory();
6827
6856
  }).map((f) => f.replace("connect-", ""));
6828
6857
  }
6829
6858
  function getConnectorDocs(name) {
6830
6859
  const connectorPath = getConnectorPath(name);
6831
6860
  const claudeMdPath = join4(connectorPath, "CLAUDE.md");
6832
- if (!existsSync3(claudeMdPath))
6861
+ if (!existsSync4(claudeMdPath))
6833
6862
  return null;
6834
6863
  const raw = readFileSync3(claudeMdPath, "utf-8");
6835
6864
  return {
@@ -6872,7 +6901,7 @@ function removeConnector(name, targetDir = process.cwd()) {
6872
6901
  const connectorName = name.startsWith("connect-") ? name : `connect-${name}`;
6873
6902
  const connectorsDir = join4(targetDir, ".connectors");
6874
6903
  const connectorPath = join4(connectorsDir, connectorName);
6875
- if (!existsSync3(connectorPath)) {
6904
+ if (!existsSync4(connectorPath)) {
6876
6905
  return false;
6877
6906
  }
6878
6907
  rmSync(connectorPath, { recursive: true });
@@ -6881,15 +6910,14 @@ function removeConnector(name, targetDir = process.cwd()) {
6881
6910
  }
6882
6911
 
6883
6912
  // src/server/auth.ts
6884
- import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync5, readdirSync as readdirSync2, rmSync as rmSync2, statSync as statSync3 } from "fs";
6913
+ import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync5, readdirSync as readdirSync3, rmSync as rmSync2, statSync as statSync4 } from "fs";
6885
6914
  import { randomBytes } from "crypto";
6886
- import { homedir as homedir5 } from "os";
6887
6915
  import { join as join6 } from "path";
6888
6916
 
6889
6917
  // src/lib/lock.ts
6890
- import { openSync, closeSync, unlinkSync, existsSync as existsSync4, statSync as statSync2 } from "fs";
6918
+ init_database();
6919
+ import { openSync, closeSync, unlinkSync, existsSync as existsSync5, statSync as statSync3 } from "fs";
6891
6920
  import { join as join5 } from "path";
6892
- import { homedir as homedir4 } from "os";
6893
6921
  import { mkdirSync as mkdirSync4 } from "fs";
6894
6922
  var LOCK_TIMEOUT_MS = 5000;
6895
6923
  var LOCK_RETRY_MS = 100;
@@ -6904,20 +6932,20 @@ class LockTimeoutError extends Error {
6904
6932
  }
6905
6933
  }
6906
6934
  function lockPath(connector) {
6907
- const dir = join5(homedir4(), ".connectors", `connect-${connector}`);
6935
+ const dir = join5(getConnectorsHome(), `connect-${connector}`);
6908
6936
  mkdirSync4(dir, { recursive: true });
6909
6937
  return join5(dir, ".write.lock");
6910
6938
  }
6911
6939
  function isStale(path) {
6912
6940
  try {
6913
- const stat = statSync2(path);
6941
+ const stat = statSync3(path);
6914
6942
  return Date.now() - stat.mtimeMs > STALE_LOCK_MS;
6915
6943
  } catch {
6916
6944
  return false;
6917
6945
  }
6918
6946
  }
6919
6947
  function tryAcquire(path) {
6920
- if (existsSync4(path) && isStale(path)) {
6948
+ if (existsSync5(path) && isStale(path)) {
6921
6949
  try {
6922
6950
  unlinkSync(path);
6923
6951
  } catch {}
@@ -6954,6 +6982,7 @@ async function withWriteLock(connector, fn) {
6954
6982
  }
6955
6983
 
6956
6984
  // src/server/auth.ts
6985
+ init_database();
6957
6986
  var FETCH_TIMEOUT = 1e4;
6958
6987
  var oauthStateStore = new Map;
6959
6988
  var GOOGLE_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
@@ -7009,12 +7038,12 @@ function getAuthType(name) {
7009
7038
  }
7010
7039
  function getConnectorConfigDir(name) {
7011
7040
  const connectorName = name.startsWith("connect-") ? name : `connect-${name}`;
7012
- return join6(homedir5(), ".connectors", connectorName);
7041
+ return join6(getConnectorsHome(), connectorName);
7013
7042
  }
7014
7043
  function getCurrentProfile(name) {
7015
7044
  const configDir = getConnectorConfigDir(name);
7016
7045
  const currentProfileFile = join6(configDir, "current_profile");
7017
- if (existsSync5(currentProfileFile)) {
7046
+ if (existsSync6(currentProfileFile)) {
7018
7047
  try {
7019
7048
  return readFileSync4(currentProfileFile, "utf-8").trim() || "default";
7020
7049
  } catch {
@@ -7029,13 +7058,13 @@ function loadProfileConfig(name) {
7029
7058
  let flatConfig = {};
7030
7059
  let dirConfig = {};
7031
7060
  const profileFile = join6(configDir, "profiles", `${profile}.json`);
7032
- if (existsSync5(profileFile)) {
7061
+ if (existsSync6(profileFile)) {
7033
7062
  try {
7034
7063
  flatConfig = JSON.parse(readFileSync4(profileFile, "utf-8"));
7035
7064
  } catch {}
7036
7065
  }
7037
7066
  const profileDirConfig = join6(configDir, "profiles", profile, "config.json");
7038
- if (existsSync5(profileDirConfig)) {
7067
+ if (existsSync6(profileDirConfig)) {
7039
7068
  try {
7040
7069
  dirConfig = JSON.parse(readFileSync4(profileDirConfig, "utf-8"));
7041
7070
  } catch {}
@@ -7049,7 +7078,7 @@ function loadTokens(name) {
7049
7078
  const configDir = getConnectorConfigDir(name);
7050
7079
  const profile = getCurrentProfile(name);
7051
7080
  const tokensFile = join6(configDir, "profiles", profile, "tokens.json");
7052
- if (existsSync5(tokensFile)) {
7081
+ if (existsSync6(tokensFile)) {
7053
7082
  try {
7054
7083
  return JSON.parse(readFileSync4(tokensFile, "utf-8"));
7055
7084
  } catch {
@@ -7117,7 +7146,7 @@ function _saveApiKey(name, key, field) {
7117
7146
  const credentialsFile = join6(configDir, "credentials.json");
7118
7147
  mkdirSync5(configDir, { recursive: true });
7119
7148
  let creds = {};
7120
- if (existsSync5(credentialsFile)) {
7149
+ if (existsSync6(credentialsFile)) {
7121
7150
  try {
7122
7151
  creds = JSON.parse(readFileSync4(credentialsFile, "utf-8"));
7123
7152
  } catch {}
@@ -7128,7 +7157,7 @@ function _saveApiKey(name, key, field) {
7128
7157
  }
7129
7158
  const profileFile = join6(configDir, "profiles", `${profile}.json`);
7130
7159
  const profileDir = join6(configDir, "profiles", profile);
7131
- if (existsSync5(profileFile)) {
7160
+ if (existsSync6(profileFile)) {
7132
7161
  let config = {};
7133
7162
  try {
7134
7163
  config = JSON.parse(readFileSync4(profileFile, "utf-8"));
@@ -7137,10 +7166,10 @@ function _saveApiKey(name, key, field) {
7137
7166
  writeFileSync3(profileFile, JSON.stringify(config, null, 2));
7138
7167
  return;
7139
7168
  }
7140
- if (existsSync5(profileDir)) {
7169
+ if (existsSync6(profileDir)) {
7141
7170
  const configFile = join6(profileDir, "config.json");
7142
7171
  let config = {};
7143
- if (existsSync5(configFile)) {
7172
+ if (existsSync6(configFile)) {
7144
7173
  try {
7145
7174
  config = JSON.parse(readFileSync4(configFile, "utf-8"));
7146
7175
  } catch {}
@@ -7169,7 +7198,7 @@ function guessKeyField(name) {
7169
7198
  function getOAuthConfig(name) {
7170
7199
  const configDir = getConnectorConfigDir(name);
7171
7200
  const credentialsFile = join6(configDir, "credentials.json");
7172
- if (existsSync5(credentialsFile)) {
7201
+ if (existsSync6(credentialsFile)) {
7173
7202
  try {
7174
7203
  const creds = JSON.parse(readFileSync4(credentialsFile, "utf-8"));
7175
7204
  return { clientId: creds.clientId, clientSecret: creds.clientSecret };
@@ -7296,14 +7325,14 @@ async function _refreshOAuthToken(name) {
7296
7325
  function listProfiles(name) {
7297
7326
  const configDir = getConnectorConfigDir(name);
7298
7327
  const profilesDir = join6(configDir, "profiles");
7299
- if (!existsSync5(profilesDir))
7328
+ if (!existsSync6(profilesDir))
7300
7329
  return ["default"];
7301
7330
  const seen = new Set;
7302
7331
  try {
7303
- const entries = readdirSync2(profilesDir);
7332
+ const entries = readdirSync3(profilesDir);
7304
7333
  for (const entry of entries) {
7305
7334
  const fullPath = join6(profilesDir, entry);
7306
- const stat = statSync3(fullPath);
7335
+ const stat = statSync4(fullPath);
7307
7336
  if (stat.isDirectory()) {
7308
7337
  seen.add(entry);
7309
7338
  } else if (entry.endsWith(".json")) {
@@ -7325,7 +7354,7 @@ function deleteProfile(name, profile) {
7325
7354
  const configDir = getConnectorConfigDir(name);
7326
7355
  const profilesDir = join6(configDir, "profiles");
7327
7356
  const profileFile = join6(profilesDir, `${profile}.json`);
7328
- if (existsSync5(profileFile)) {
7357
+ if (existsSync6(profileFile)) {
7329
7358
  rmSync2(profileFile);
7330
7359
  if (getCurrentProfile(name) === profile) {
7331
7360
  switchProfile(name, "default");
@@ -7333,7 +7362,7 @@ function deleteProfile(name, profile) {
7333
7362
  return true;
7334
7363
  }
7335
7364
  const profileDir = join6(profilesDir, profile);
7336
- if (existsSync5(profileDir)) {
7365
+ if (existsSync6(profileDir)) {
7337
7366
  rmSync2(profileDir, { recursive: true });
7338
7367
  if (getCurrentProfile(name) === profile) {
7339
7368
  switchProfile(name, "default");
@@ -7366,7 +7395,7 @@ function resolveDashboardDir() {
7366
7395
  }
7367
7396
  candidates.push(join7(process.cwd(), "dashboard", "dist"));
7368
7397
  for (const candidate of candidates) {
7369
- if (existsSync6(candidate))
7398
+ if (existsSync7(candidate))
7370
7399
  return candidate;
7371
7400
  }
7372
7401
  return join7(process.cwd(), "dashboard", "dist");
@@ -7471,7 +7500,7 @@ function oauthPage(type, title, message, hint, extra) {
7471
7500
  </body></html>`;
7472
7501
  }
7473
7502
  function serveStaticFile(filePath) {
7474
- if (!existsSync6(filePath))
7503
+ if (!existsSync7(filePath))
7475
7504
  return null;
7476
7505
  const ext = extname(filePath);
7477
7506
  const contentType = MIME_TYPES[ext] || "application/octet-stream";
@@ -7495,7 +7524,7 @@ async function startServer(requestedPort, options) {
7495
7524
  const shouldOpen = options?.open ?? true;
7496
7525
  loadConnectorVersions();
7497
7526
  const dashboardDir = resolveDashboardDir();
7498
- const dashboardExists = existsSync6(dashboardDir);
7527
+ const dashboardExists = existsSync7(dashboardDir);
7499
7528
  if (!dashboardExists) {
7500
7529
  console.error(`
7501
7530
  Dashboard not found at: ${dashboardDir}`);
@@ -7649,7 +7678,7 @@ Dashboard not found at: ${dashboardDir}`);
7649
7678
  const { getPromotedConnectors: getPromotedConnectors2 } = await Promise.resolve().then(() => (init_promotions(), exports_promotions));
7650
7679
  const limit = parseInt(url2.searchParams.get("limit") || "10", 10);
7651
7680
  const days = parseInt(url2.searchParams.get("days") || "7", 10);
7652
- const db = getDatabase2();
7681
+ const db = getDatabase3();
7653
7682
  const top = getTopConnectors2(limit, days, db);
7654
7683
  const promoted = new Set(getPromotedConnectors2(db));
7655
7684
  return json(top.map((t) => ({ ...t, promoted: promoted.has(t.connector) })), 200, port);
@@ -7660,12 +7689,12 @@ Dashboard not found at: ${dashboardDir}`);
7660
7689
  if (!getConnector(name))
7661
7690
  return json({ error: "Connector not found" }, 404, port);
7662
7691
  const { promoteConnector: promoteConnector2 } = await Promise.resolve().then(() => (init_promotions(), exports_promotions));
7663
- promoteConnector2(name, getDatabase2());
7692
+ promoteConnector2(name, getDatabase3());
7664
7693
  return json({ success: true, connector: name }, 200, port);
7665
7694
  }
7666
7695
  if (promoteMatch && method === "DELETE") {
7667
7696
  const { demoteConnector: demoteConnector2 } = await Promise.resolve().then(() => (init_promotions(), exports_promotions));
7668
- const removed = demoteConnector2(promoteMatch[1], getDatabase2());
7697
+ const removed = demoteConnector2(promoteMatch[1], getDatabase3());
7669
7698
  return json({ success: removed, connector: promoteMatch[1] }, 200, port);
7670
7699
  }
7671
7700
  if (path === "/api/llm" && method === "GET") {
@@ -7701,19 +7730,19 @@ Dashboard not found at: ${dashboardDir}`);
7701
7730
  }
7702
7731
  }
7703
7732
  if (path === "/api/jobs" && method === "GET") {
7704
- return json(listJobs(getDatabase2()), 200, port);
7733
+ return json(listJobs(getDatabase3()), 200, port);
7705
7734
  }
7706
7735
  if (path === "/api/jobs" && method === "POST") {
7707
7736
  const body = await req.json().catch(() => ({}));
7708
7737
  if (!body.name || !body.connector || !body.command || !body.cron)
7709
7738
  return json({ error: "name, connector, command, cron required" }, 400, port);
7710
- const job = createJob({ name: body.name, connector: body.connector, command: body.command, args: body.args ?? [], cron: body.cron, strip: !!body.strip }, getDatabase2());
7739
+ const job = createJob({ name: body.name, connector: body.connector, command: body.command, args: body.args ?? [], cron: body.cron, strip: !!body.strip }, getDatabase3());
7711
7740
  return json(job, 201, port);
7712
7741
  }
7713
7742
  const jobMatch = path.match(/^\/api\/jobs\/([^/]+)$/);
7714
7743
  if (jobMatch) {
7715
- const db = getDatabase2();
7716
- const job = getJobByName(jobMatch[1]) ?? getDatabase2().query("SELECT * FROM connector_jobs WHERE id = ?").get(jobMatch[1]);
7744
+ const db = getDatabase3();
7745
+ const job = getJobByName(jobMatch[1]) ?? getDatabase3().query("SELECT * FROM connector_jobs WHERE id = ?").get(jobMatch[1]);
7717
7746
  if (!job && method !== "DELETE")
7718
7747
  return json({ error: "Job not found" }, 404, port);
7719
7748
  if (method === "GET")
@@ -7734,7 +7763,7 @@ Dashboard not found at: ${dashboardDir}`);
7734
7763
  }
7735
7764
  const jobRunMatch = path.match(/^\/api\/jobs\/([^/]+)\/run$/);
7736
7765
  if (jobRunMatch && method === "POST") {
7737
- const db = getDatabase2();
7766
+ const db = getDatabase3();
7738
7767
  const job = getJobByName(jobRunMatch[1], db);
7739
7768
  if (!job)
7740
7769
  return json({ error: "Job not found" }, 404, port);
@@ -7742,18 +7771,18 @@ Dashboard not found at: ${dashboardDir}`);
7742
7771
  return json(result, 200, port);
7743
7772
  }
7744
7773
  if (path === "/api/workflows" && method === "GET") {
7745
- return json(listWorkflows(getDatabase2()), 200, port);
7774
+ return json(listWorkflows(getDatabase3()), 200, port);
7746
7775
  }
7747
7776
  if (path === "/api/workflows" && method === "POST") {
7748
7777
  const body = await req.json().catch(() => ({}));
7749
7778
  if (!body.name || !body.steps)
7750
7779
  return json({ error: "name and steps required" }, 400, port);
7751
- const wf = createWorkflow({ name: body.name, steps: body.steps }, getDatabase2());
7780
+ const wf = createWorkflow({ name: body.name, steps: body.steps }, getDatabase3());
7752
7781
  return json(wf, 201, port);
7753
7782
  }
7754
7783
  const wfMatch = path.match(/^\/api\/workflows\/([^/]+)$/);
7755
7784
  if (wfMatch) {
7756
- const db = getDatabase2();
7785
+ const db = getDatabase3();
7757
7786
  const wf = getWorkflowByName(wfMatch[1], db);
7758
7787
  if (!wf)
7759
7788
  return json({ error: "Workflow not found" }, 404, port);
@@ -7766,7 +7795,7 @@ Dashboard not found at: ${dashboardDir}`);
7766
7795
  }
7767
7796
  const wfRunMatch = path.match(/^\/api\/workflows\/([^/]+)\/run$/);
7768
7797
  if (wfRunMatch && method === "POST") {
7769
- const wf = getWorkflowByName(wfRunMatch[1], getDatabase2());
7798
+ const wf = getWorkflowByName(wfRunMatch[1], getDatabase3());
7770
7799
  if (!wf)
7771
7800
  return json({ error: "Workflow not found" }, 404, port);
7772
7801
  const result = await runWorkflow(wf);
@@ -7812,10 +7841,10 @@ Dashboard not found at: ${dashboardDir}`);
7812
7841
  return json({ error: "Invalid connector name" }, 400, port);
7813
7842
  try {
7814
7843
  const profiles = listProfiles(name);
7815
- const configDir = join7(homedir6(), ".connectors", name.startsWith("connect-") ? name : `connect-${name}`);
7844
+ const configDir = join7(getConnectorsHome(), name.startsWith("connect-") ? name : `connect-${name}`);
7816
7845
  const currentProfileFile = join7(configDir, "current_profile");
7817
7846
  let current = "default";
7818
- if (existsSync6(currentProfileFile)) {
7847
+ if (existsSync7(currentProfileFile)) {
7819
7848
  try {
7820
7849
  current = readFileSync5(currentProfileFile, "utf-8").trim() || "default";
7821
7850
  } catch {}
@@ -7864,19 +7893,19 @@ Dashboard not found at: ${dashboardDir}`);
7864
7893
  }
7865
7894
  if (path === "/api/export" && method === "GET") {
7866
7895
  try {
7867
- const connectDir = join7(homedir6(), ".connectors");
7896
+ const connectDir = getConnectorsHome();
7868
7897
  const result = {};
7869
- if (existsSync6(connectDir)) {
7870
- const entries = readdirSync3(connectDir, { withFileTypes: true });
7898
+ if (existsSync7(connectDir)) {
7899
+ const entries = readdirSync4(connectDir, { withFileTypes: true });
7871
7900
  for (const entry of entries) {
7872
7901
  if (!entry.isDirectory() || !entry.name.startsWith("connect-"))
7873
7902
  continue;
7874
7903
  const connectorName = entry.name.replace(/^connect-/, "");
7875
7904
  const profilesDir = join7(connectDir, entry.name, "profiles");
7876
- if (!existsSync6(profilesDir))
7905
+ if (!existsSync7(profilesDir))
7877
7906
  continue;
7878
7907
  const profiles = {};
7879
- const profileEntries = readdirSync3(profilesDir, { withFileTypes: true });
7908
+ const profileEntries = readdirSync4(profilesDir, { withFileTypes: true });
7880
7909
  for (const pEntry of profileEntries) {
7881
7910
  if (pEntry.isFile() && pEntry.name.endsWith(".json")) {
7882
7911
  const profileName = basename(pEntry.name, ".json");
@@ -7887,7 +7916,7 @@ Dashboard not found at: ${dashboardDir}`);
7887
7916
  }
7888
7917
  if (pEntry.isDirectory()) {
7889
7918
  const configPath = join7(profilesDir, pEntry.name, "config.json");
7890
- if (existsSync6(configPath)) {
7919
+ if (existsSync7(configPath)) {
7891
7920
  try {
7892
7921
  const config = JSON.parse(readFileSync5(configPath, "utf-8"));
7893
7922
  profiles[pEntry.name] = config;
@@ -7924,7 +7953,7 @@ Dashboard not found at: ${dashboardDir}`);
7924
7953
  return json({ error: "Invalid import format: missing 'connectors' object" }, 400, port);
7925
7954
  }
7926
7955
  let imported = 0;
7927
- const connectDir = join7(homedir6(), ".connectors");
7956
+ const connectDir = getConnectorsHome();
7928
7957
  for (const [connectorName, data] of Object.entries(body.connectors)) {
7929
7958
  if (!isValidConnectorName(connectorName))
7930
7959
  continue;
@@ -8012,8 +8041,8 @@ Dashboard not found at: ${dashboardDir}`);
8012
8041
  process.on("SIGINT", shutdown);
8013
8042
  process.on("SIGTERM", shutdown);
8014
8043
  const { startScheduler: startScheduler2 } = await Promise.resolve().then(() => (init_scheduler(), exports_scheduler));
8015
- const { getDatabase: getDatabase2 } = await Promise.resolve().then(() => (init_database(), exports_database));
8016
- startScheduler2(getDatabase2());
8044
+ const { getDatabase: getDatabase3 } = await Promise.resolve().then(() => (init_database(), exports_database));
8045
+ startScheduler2(getDatabase3());
8017
8046
  const url = `http://localhost:${port}`;
8018
8047
  console.log(`Connectors Dashboard running at ${url}`);
8019
8048
  if (shouldOpen) {
@@ -1,4 +1,10 @@
1
1
  import { Database } from "bun:sqlite";
2
+ /**
3
+ * Get the connectors home directory.
4
+ * New default: ~/.hasna/connectors/
5
+ * Auto-migrates from ~/.connectors/ if the new dir doesn't exist yet.
6
+ */
7
+ export declare function getConnectorsHome(): string;
2
8
  export declare function getDatabase(path?: string): Database;
3
9
  export declare function closeDatabase(): void;
4
10
  /** ISO timestamp string */