@hasna/connectors 1.1.12 → 1.1.13
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/index.js +230 -156
- package/bin/mcp.js +115 -41
- package/bin/serve.js +144 -68
- package/dist/lib/lock.d.ts +22 -0
- package/dist/lib/lock.test.d.ts +1 -0
- package/dist/server/auth.d.ts +4 -2
- package/package.json +1 -2
package/bin/mcp.js
CHANGED
|
@@ -26,6 +26,7 @@ var __export = (target, all) => {
|
|
|
26
26
|
set: (newValue) => all[name] = () => newValue
|
|
27
27
|
});
|
|
28
28
|
};
|
|
29
|
+
var __require = import.meta.require;
|
|
29
30
|
|
|
30
31
|
// node_modules/ajv/dist/compile/codegen/code.js
|
|
31
32
|
var require_code = __commonJS((exports) => {
|
|
@@ -25571,9 +25572,79 @@ function removeConnector(name, targetDir = process.cwd()) {
|
|
|
25571
25572
|
}
|
|
25572
25573
|
|
|
25573
25574
|
// src/server/auth.ts
|
|
25574
|
-
import { existsSync as
|
|
25575
|
-
import { homedir as
|
|
25575
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, readdirSync as readdirSync2, rmSync as rmSync2, statSync as statSync2 } from "fs";
|
|
25576
|
+
import { homedir as homedir3 } from "os";
|
|
25577
|
+
import { join as join4 } from "path";
|
|
25578
|
+
|
|
25579
|
+
// src/lib/lock.ts
|
|
25580
|
+
import { openSync, closeSync, unlinkSync, existsSync as existsSync3 } from "fs";
|
|
25576
25581
|
import { join as join3 } from "path";
|
|
25582
|
+
import { homedir as homedir2 } from "os";
|
|
25583
|
+
import { mkdirSync as mkdirSync2 } from "fs";
|
|
25584
|
+
var LOCK_TIMEOUT_MS = 5000;
|
|
25585
|
+
var LOCK_RETRY_MS = 100;
|
|
25586
|
+
var STALE_LOCK_MS = 30000;
|
|
25587
|
+
|
|
25588
|
+
class LockTimeoutError extends Error {
|
|
25589
|
+
connector;
|
|
25590
|
+
constructor(connector) {
|
|
25591
|
+
super(`Could not acquire write lock for connector "${connector}" within ${LOCK_TIMEOUT_MS}ms. Another agent may be writing. Try again shortly.`);
|
|
25592
|
+
this.connector = connector;
|
|
25593
|
+
this.name = "LockTimeoutError";
|
|
25594
|
+
}
|
|
25595
|
+
}
|
|
25596
|
+
function lockPath(connector) {
|
|
25597
|
+
const dir = join3(homedir2(), ".connectors", `connect-${connector}`);
|
|
25598
|
+
mkdirSync2(dir, { recursive: true });
|
|
25599
|
+
return join3(dir, ".write.lock");
|
|
25600
|
+
}
|
|
25601
|
+
function isStale(path) {
|
|
25602
|
+
try {
|
|
25603
|
+
const { statSync: statSync2 } = __require("fs");
|
|
25604
|
+
const stat = statSync2(path);
|
|
25605
|
+
return Date.now() - stat.mtimeMs > STALE_LOCK_MS;
|
|
25606
|
+
} catch {
|
|
25607
|
+
return false;
|
|
25608
|
+
}
|
|
25609
|
+
}
|
|
25610
|
+
function tryAcquire(path) {
|
|
25611
|
+
if (existsSync3(path) && isStale(path)) {
|
|
25612
|
+
try {
|
|
25613
|
+
unlinkSync(path);
|
|
25614
|
+
} catch {}
|
|
25615
|
+
}
|
|
25616
|
+
try {
|
|
25617
|
+
const fd = openSync(path, "wx");
|
|
25618
|
+
closeSync(fd);
|
|
25619
|
+
return true;
|
|
25620
|
+
} catch (e) {
|
|
25621
|
+
if (e.code === "EEXIST")
|
|
25622
|
+
return false;
|
|
25623
|
+
throw e;
|
|
25624
|
+
}
|
|
25625
|
+
}
|
|
25626
|
+
function release(path) {
|
|
25627
|
+
try {
|
|
25628
|
+
unlinkSync(path);
|
|
25629
|
+
} catch {}
|
|
25630
|
+
}
|
|
25631
|
+
async function withWriteLock(connector, fn) {
|
|
25632
|
+
const path = lockPath(connector);
|
|
25633
|
+
const deadline = Date.now() + LOCK_TIMEOUT_MS;
|
|
25634
|
+
while (Date.now() < deadline) {
|
|
25635
|
+
if (tryAcquire(path)) {
|
|
25636
|
+
try {
|
|
25637
|
+
return await fn();
|
|
25638
|
+
} finally {
|
|
25639
|
+
release(path);
|
|
25640
|
+
}
|
|
25641
|
+
}
|
|
25642
|
+
await new Promise((resolve) => setTimeout(resolve, LOCK_RETRY_MS));
|
|
25643
|
+
}
|
|
25644
|
+
throw new LockTimeoutError(connector);
|
|
25645
|
+
}
|
|
25646
|
+
|
|
25647
|
+
// src/server/auth.ts
|
|
25577
25648
|
var oauthStateStore = new Map;
|
|
25578
25649
|
var GOOGLE_SCOPES = {
|
|
25579
25650
|
gmail: [
|
|
@@ -25626,12 +25697,12 @@ function getAuthType(name) {
|
|
|
25626
25697
|
}
|
|
25627
25698
|
function getConnectorConfigDir(name) {
|
|
25628
25699
|
const connectorName = name.startsWith("connect-") ? name : `connect-${name}`;
|
|
25629
|
-
return
|
|
25700
|
+
return join4(homedir3(), ".connectors", connectorName);
|
|
25630
25701
|
}
|
|
25631
25702
|
function getCurrentProfile(name) {
|
|
25632
25703
|
const configDir = getConnectorConfigDir(name);
|
|
25633
|
-
const currentProfileFile =
|
|
25634
|
-
if (
|
|
25704
|
+
const currentProfileFile = join4(configDir, "current_profile");
|
|
25705
|
+
if (existsSync4(currentProfileFile)) {
|
|
25635
25706
|
try {
|
|
25636
25707
|
return readFileSync3(currentProfileFile, "utf-8").trim() || "default";
|
|
25637
25708
|
} catch {
|
|
@@ -25645,14 +25716,14 @@ function loadProfileConfig(name) {
|
|
|
25645
25716
|
const profile = getCurrentProfile(name);
|
|
25646
25717
|
let flatConfig = {};
|
|
25647
25718
|
let dirConfig = {};
|
|
25648
|
-
const profileFile =
|
|
25649
|
-
if (
|
|
25719
|
+
const profileFile = join4(configDir, "profiles", `${profile}.json`);
|
|
25720
|
+
if (existsSync4(profileFile)) {
|
|
25650
25721
|
try {
|
|
25651
25722
|
flatConfig = JSON.parse(readFileSync3(profileFile, "utf-8"));
|
|
25652
25723
|
} catch {}
|
|
25653
25724
|
}
|
|
25654
|
-
const profileDirConfig =
|
|
25655
|
-
if (
|
|
25725
|
+
const profileDirConfig = join4(configDir, "profiles", profile, "config.json");
|
|
25726
|
+
if (existsSync4(profileDirConfig)) {
|
|
25656
25727
|
try {
|
|
25657
25728
|
dirConfig = JSON.parse(readFileSync3(profileDirConfig, "utf-8"));
|
|
25658
25729
|
} catch {}
|
|
@@ -25665,8 +25736,8 @@ function loadProfileConfig(name) {
|
|
|
25665
25736
|
function loadTokens(name) {
|
|
25666
25737
|
const configDir = getConnectorConfigDir(name);
|
|
25667
25738
|
const profile = getCurrentProfile(name);
|
|
25668
|
-
const tokensFile =
|
|
25669
|
-
if (
|
|
25739
|
+
const tokensFile = join4(configDir, "profiles", profile, "tokens.json");
|
|
25740
|
+
if (existsSync4(tokensFile)) {
|
|
25670
25741
|
try {
|
|
25671
25742
|
return JSON.parse(readFileSync3(tokensFile, "utf-8"));
|
|
25672
25743
|
} catch {
|
|
@@ -25713,15 +25784,18 @@ function getAuthStatus(name) {
|
|
|
25713
25784
|
envVarTotalCount
|
|
25714
25785
|
};
|
|
25715
25786
|
}
|
|
25716
|
-
function saveApiKey(name, key, field) {
|
|
25787
|
+
async function saveApiKey(name, key, field) {
|
|
25788
|
+
return withWriteLock(name, () => _saveApiKey(name, key, field));
|
|
25789
|
+
}
|
|
25790
|
+
function _saveApiKey(name, key, field) {
|
|
25717
25791
|
const configDir = getConnectorConfigDir(name);
|
|
25718
25792
|
const profile = getCurrentProfile(name);
|
|
25719
25793
|
const keyField = field || guessKeyField(name);
|
|
25720
25794
|
if (keyField === "clientId" || keyField === "clientSecret") {
|
|
25721
|
-
const credentialsFile =
|
|
25722
|
-
|
|
25795
|
+
const credentialsFile = join4(configDir, "credentials.json");
|
|
25796
|
+
mkdirSync3(configDir, { recursive: true });
|
|
25723
25797
|
let creds = {};
|
|
25724
|
-
if (
|
|
25798
|
+
if (existsSync4(credentialsFile)) {
|
|
25725
25799
|
try {
|
|
25726
25800
|
creds = JSON.parse(readFileSync3(credentialsFile, "utf-8"));
|
|
25727
25801
|
} catch {}
|
|
@@ -25730,9 +25804,9 @@ function saveApiKey(name, key, field) {
|
|
|
25730
25804
|
writeFileSync2(credentialsFile, JSON.stringify(creds, null, 2));
|
|
25731
25805
|
return;
|
|
25732
25806
|
}
|
|
25733
|
-
const profileFile =
|
|
25734
|
-
const profileDir =
|
|
25735
|
-
if (
|
|
25807
|
+
const profileFile = join4(configDir, "profiles", `${profile}.json`);
|
|
25808
|
+
const profileDir = join4(configDir, "profiles", profile);
|
|
25809
|
+
if (existsSync4(profileFile)) {
|
|
25736
25810
|
let config2 = {};
|
|
25737
25811
|
try {
|
|
25738
25812
|
config2 = JSON.parse(readFileSync3(profileFile, "utf-8"));
|
|
@@ -25741,10 +25815,10 @@ function saveApiKey(name, key, field) {
|
|
|
25741
25815
|
writeFileSync2(profileFile, JSON.stringify(config2, null, 2));
|
|
25742
25816
|
return;
|
|
25743
25817
|
}
|
|
25744
|
-
if (
|
|
25745
|
-
const configFile =
|
|
25818
|
+
if (existsSync4(profileDir)) {
|
|
25819
|
+
const configFile = join4(profileDir, "config.json");
|
|
25746
25820
|
let config2 = {};
|
|
25747
|
-
if (
|
|
25821
|
+
if (existsSync4(configFile)) {
|
|
25748
25822
|
try {
|
|
25749
25823
|
config2 = JSON.parse(readFileSync3(configFile, "utf-8"));
|
|
25750
25824
|
} catch {}
|
|
@@ -25753,8 +25827,8 @@ function saveApiKey(name, key, field) {
|
|
|
25753
25827
|
writeFileSync2(configFile, JSON.stringify(config2, null, 2));
|
|
25754
25828
|
return;
|
|
25755
25829
|
}
|
|
25756
|
-
|
|
25757
|
-
writeFileSync2(
|
|
25830
|
+
mkdirSync3(profileDir, { recursive: true });
|
|
25831
|
+
writeFileSync2(join4(profileDir, "config.json"), JSON.stringify({ [keyField]: key }, null, 2));
|
|
25758
25832
|
}
|
|
25759
25833
|
function guessKeyField(name) {
|
|
25760
25834
|
const docs = getConnectorDocs(name);
|
|
@@ -25772,17 +25846,17 @@ function guessKeyField(name) {
|
|
|
25772
25846
|
}
|
|
25773
25847
|
|
|
25774
25848
|
// src/lib/runner.ts
|
|
25775
|
-
import { existsSync as
|
|
25776
|
-
import { join as
|
|
25849
|
+
import { existsSync as existsSync5 } from "fs";
|
|
25850
|
+
import { join as join5, dirname as dirname3 } from "path";
|
|
25777
25851
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
25778
25852
|
import { spawn } from "child_process";
|
|
25779
25853
|
var __dirname3 = dirname3(fileURLToPath3(import.meta.url));
|
|
25780
25854
|
function resolveConnectorsDir2() {
|
|
25781
|
-
const fromBin =
|
|
25782
|
-
if (
|
|
25855
|
+
const fromBin = join5(__dirname3, "..", "connectors");
|
|
25856
|
+
if (existsSync5(fromBin))
|
|
25783
25857
|
return fromBin;
|
|
25784
|
-
const fromSrc =
|
|
25785
|
-
if (
|
|
25858
|
+
const fromSrc = join5(__dirname3, "..", "..", "connectors");
|
|
25859
|
+
if (existsSync5(fromSrc))
|
|
25786
25860
|
return fromSrc;
|
|
25787
25861
|
return fromBin;
|
|
25788
25862
|
}
|
|
@@ -25822,9 +25896,9 @@ function buildEnvWithCredentials(connectorName, baseEnv) {
|
|
|
25822
25896
|
}
|
|
25823
25897
|
function getConnectorCliPath(name) {
|
|
25824
25898
|
const safeName = name.replace(/[^a-z0-9-]/g, "");
|
|
25825
|
-
const connectorDir =
|
|
25826
|
-
const cliPath =
|
|
25827
|
-
if (
|
|
25899
|
+
const connectorDir = join5(CONNECTORS_DIR2, `connect-${safeName}`);
|
|
25900
|
+
const cliPath = join5(connectorDir, "src", "cli", "index.ts");
|
|
25901
|
+
if (existsSync5(cliPath))
|
|
25828
25902
|
return cliPath;
|
|
25829
25903
|
return null;
|
|
25830
25904
|
}
|
|
@@ -25905,17 +25979,17 @@ async function getConnectorCommandHelp(name, command) {
|
|
|
25905
25979
|
|
|
25906
25980
|
// src/db/database.ts
|
|
25907
25981
|
import { Database } from "bun:sqlite";
|
|
25908
|
-
import { join as
|
|
25909
|
-
import { homedir as
|
|
25910
|
-
import { mkdirSync as
|
|
25911
|
-
var DB_DIR =
|
|
25912
|
-
var DB_PATH =
|
|
25982
|
+
import { join as join6 } from "path";
|
|
25983
|
+
import { homedir as homedir4 } from "os";
|
|
25984
|
+
import { mkdirSync as mkdirSync4 } from "fs";
|
|
25985
|
+
var DB_DIR = join6(homedir4(), ".connectors");
|
|
25986
|
+
var DB_PATH = join6(DB_DIR, "connectors.db");
|
|
25913
25987
|
var _db = null;
|
|
25914
25988
|
function getDatabase(path) {
|
|
25915
25989
|
if (_db)
|
|
25916
25990
|
return _db;
|
|
25917
25991
|
const dbPath = path ?? DB_PATH;
|
|
25918
|
-
|
|
25992
|
+
mkdirSync4(join6(dbPath, ".."), { recursive: true });
|
|
25919
25993
|
_db = new Database(dbPath);
|
|
25920
25994
|
_db.run("PRAGMA journal_mode = WAL");
|
|
25921
25995
|
migrate(_db);
|
|
@@ -25997,7 +26071,7 @@ function listAgents(db) {
|
|
|
25997
26071
|
// package.json
|
|
25998
26072
|
var package_default = {
|
|
25999
26073
|
name: "@hasna/connectors",
|
|
26000
|
-
version: "1.1.
|
|
26074
|
+
version: "1.1.13",
|
|
26001
26075
|
description: "Open source connector library - Install API connectors with a single command",
|
|
26002
26076
|
type: "module",
|
|
26003
26077
|
bin: {
|
|
@@ -26295,7 +26369,7 @@ server.registerTool("configure_auth", {
|
|
|
26295
26369
|
}
|
|
26296
26370
|
}, async ({ name, key, field }) => {
|
|
26297
26371
|
try {
|
|
26298
|
-
saveApiKey(name, key, field);
|
|
26372
|
+
await saveApiKey(name, key, field);
|
|
26299
26373
|
return {
|
|
26300
26374
|
content: [
|
|
26301
26375
|
{
|
|
@@ -26485,7 +26559,7 @@ server.registerTool("setup_connector", {
|
|
|
26485
26559
|
}
|
|
26486
26560
|
if (key) {
|
|
26487
26561
|
try {
|
|
26488
|
-
saveApiKey(name, key, field);
|
|
26562
|
+
await saveApiKey(name, key, field);
|
|
26489
26563
|
} catch (error2) {
|
|
26490
26564
|
return {
|
|
26491
26565
|
content: [
|