@hasna/connectors 1.1.8 → 1.1.9
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 +59 -240
- package/bin/mcp.js +31 -98
- package/bin/serve.js +35 -104
- package/dist/index.js +12 -78
- package/dist/lib/installer.d.ts +7 -6
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -9471,8 +9471,7 @@ var require_cli_spinners = __commonJS((exports, module) => {
|
|
|
9471
9471
|
});
|
|
9472
9472
|
|
|
9473
9473
|
// src/lib/installer.ts
|
|
9474
|
-
import { existsSync as existsSync2,
|
|
9475
|
-
import { homedir } from "os";
|
|
9474
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync, statSync } from "fs";
|
|
9476
9475
|
import { join as join2, dirname as dirname2 } from "path";
|
|
9477
9476
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9478
9477
|
function resolveConnectorsDir() {
|
|
@@ -9488,11 +9487,7 @@ function getConnectorPath(name) {
|
|
|
9488
9487
|
const connectorName = name.startsWith("connect-") ? name : `connect-${name}`;
|
|
9489
9488
|
return join2(CONNECTORS_DIR, connectorName);
|
|
9490
9489
|
}
|
|
9491
|
-
function connectorExists(name) {
|
|
9492
|
-
return existsSync2(getConnectorPath(name));
|
|
9493
|
-
}
|
|
9494
9490
|
function installConnector(name, options = {}) {
|
|
9495
|
-
const { targetDir = process.cwd(), overwrite = false } = options;
|
|
9496
9491
|
if (!/^[a-z0-9-]+$/.test(name)) {
|
|
9497
9492
|
return {
|
|
9498
9493
|
connector: name,
|
|
@@ -9500,10 +9495,7 @@ function installConnector(name, options = {}) {
|
|
|
9500
9495
|
error: `Invalid connector name '${name}'`
|
|
9501
9496
|
};
|
|
9502
9497
|
}
|
|
9503
|
-
const connectorName = name.startsWith("connect-") ? name : `connect-${name}`;
|
|
9504
9498
|
const sourcePath = getConnectorPath(name);
|
|
9505
|
-
const destDir = join2(targetDir, ".connectors");
|
|
9506
|
-
const destPath = join2(destDir, connectorName);
|
|
9507
9499
|
if (!existsSync2(sourcePath)) {
|
|
9508
9500
|
return {
|
|
9509
9501
|
connector: name,
|
|
@@ -9511,71 +9503,18 @@ function installConnector(name, options = {}) {
|
|
|
9511
9503
|
error: `Connector '${name}' not found`
|
|
9512
9504
|
};
|
|
9513
9505
|
}
|
|
9514
|
-
|
|
9515
|
-
|
|
9516
|
-
|
|
9517
|
-
|
|
9518
|
-
|
|
9519
|
-
path: destPath
|
|
9520
|
-
};
|
|
9521
|
-
}
|
|
9522
|
-
try {
|
|
9523
|
-
if (!existsSync2(destDir)) {
|
|
9524
|
-
mkdirSync(destDir, { recursive: true });
|
|
9525
|
-
}
|
|
9526
|
-
cpSync(sourcePath, destPath, { recursive: true });
|
|
9527
|
-
const homeCredDir = join2(homedir(), ".connectors", connectorName);
|
|
9528
|
-
if (existsSync2(homeCredDir)) {
|
|
9529
|
-
const filesToCopy = ["credentials.json", "current_profile"];
|
|
9530
|
-
for (const file of filesToCopy) {
|
|
9531
|
-
const src = join2(homeCredDir, file);
|
|
9532
|
-
if (existsSync2(src)) {
|
|
9533
|
-
cpSync(src, join2(destPath, file));
|
|
9534
|
-
}
|
|
9535
|
-
}
|
|
9536
|
-
const profilesDir = join2(homeCredDir, "profiles");
|
|
9537
|
-
if (existsSync2(profilesDir)) {
|
|
9538
|
-
cpSync(profilesDir, join2(destPath, "profiles"), { recursive: true });
|
|
9539
|
-
}
|
|
9540
|
-
}
|
|
9541
|
-
updateConnectorsIndex(destDir);
|
|
9542
|
-
return {
|
|
9543
|
-
connector: name,
|
|
9544
|
-
success: true,
|
|
9545
|
-
path: destPath
|
|
9546
|
-
};
|
|
9547
|
-
} catch (error) {
|
|
9548
|
-
return {
|
|
9549
|
-
connector: name,
|
|
9550
|
-
success: false,
|
|
9551
|
-
error: error instanceof Error ? error.message : "Unknown error"
|
|
9552
|
-
};
|
|
9553
|
-
}
|
|
9554
|
-
}
|
|
9555
|
-
function updateConnectorsIndex(connectorsDir) {
|
|
9556
|
-
const indexPath = join2(connectorsDir, "index.ts");
|
|
9557
|
-
const connectors = readdirSync(connectorsDir).filter((f) => f.startsWith("connect-") && !f.includes("."));
|
|
9558
|
-
const exports = connectors.map((c) => {
|
|
9559
|
-
const name = c.replace("connect-", "");
|
|
9560
|
-
return `export * as ${name} from './${c}/src/index.js';`;
|
|
9561
|
-
}).join(`
|
|
9562
|
-
`);
|
|
9563
|
-
const content = `/**
|
|
9564
|
-
* Auto-generated index of installed connectors
|
|
9565
|
-
* Do not edit manually - run 'connectors install' to update
|
|
9566
|
-
*/
|
|
9567
|
-
|
|
9568
|
-
${exports}
|
|
9569
|
-
`;
|
|
9570
|
-
writeFileSync(indexPath, content);
|
|
9506
|
+
return {
|
|
9507
|
+
connector: name,
|
|
9508
|
+
success: true,
|
|
9509
|
+
path: sourcePath
|
|
9510
|
+
};
|
|
9571
9511
|
}
|
|
9572
|
-
function getInstalledConnectors(
|
|
9573
|
-
|
|
9574
|
-
if (!existsSync2(connectorsDir)) {
|
|
9512
|
+
function getInstalledConnectors() {
|
|
9513
|
+
if (!existsSync2(CONNECTORS_DIR)) {
|
|
9575
9514
|
return [];
|
|
9576
9515
|
}
|
|
9577
|
-
return readdirSync(
|
|
9578
|
-
const fullPath = join2(
|
|
9516
|
+
return readdirSync(CONNECTORS_DIR).filter((f) => {
|
|
9517
|
+
const fullPath = join2(CONNECTORS_DIR, f);
|
|
9579
9518
|
return f.startsWith("connect-") && statSync(fullPath).isDirectory();
|
|
9580
9519
|
}).map((f) => f.replace("connect-", ""));
|
|
9581
9520
|
}
|
|
@@ -9621,16 +9560,8 @@ function parseEnvVarsTable(section) {
|
|
|
9621
9560
|
}
|
|
9622
9561
|
return vars;
|
|
9623
9562
|
}
|
|
9624
|
-
function removeConnector(name
|
|
9625
|
-
|
|
9626
|
-
const connectorsDir = join2(targetDir, ".connectors");
|
|
9627
|
-
const connectorPath = join2(connectorsDir, connectorName);
|
|
9628
|
-
if (!existsSync2(connectorPath)) {
|
|
9629
|
-
return false;
|
|
9630
|
-
}
|
|
9631
|
-
rmSync(connectorPath, { recursive: true });
|
|
9632
|
-
updateConnectorsIndex(connectorsDir);
|
|
9633
|
-
return true;
|
|
9563
|
+
function removeConnector(name) {
|
|
9564
|
+
return false;
|
|
9634
9565
|
}
|
|
9635
9566
|
var __dirname2, CONNECTORS_DIR;
|
|
9636
9567
|
var init_installer = __esm(() => {
|
|
@@ -9639,9 +9570,9 @@ var init_installer = __esm(() => {
|
|
|
9639
9570
|
});
|
|
9640
9571
|
|
|
9641
9572
|
// src/server/auth.ts
|
|
9642
|
-
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync
|
|
9573
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync, mkdirSync, readdirSync as readdirSync2, rmSync, statSync as statSync2 } from "fs";
|
|
9643
9574
|
import { randomBytes } from "crypto";
|
|
9644
|
-
import { homedir
|
|
9575
|
+
import { homedir } from "os";
|
|
9645
9576
|
import { join as join3 } from "path";
|
|
9646
9577
|
function getAuthType(name) {
|
|
9647
9578
|
const docs = getConnectorDocs(name);
|
|
@@ -9656,7 +9587,7 @@ function getAuthType(name) {
|
|
|
9656
9587
|
}
|
|
9657
9588
|
function getConnectorConfigDir(name) {
|
|
9658
9589
|
const connectorName = name.startsWith("connect-") ? name : `connect-${name}`;
|
|
9659
|
-
return join3(
|
|
9590
|
+
return join3(homedir(), ".connectors", connectorName);
|
|
9660
9591
|
}
|
|
9661
9592
|
function getCurrentProfile(name) {
|
|
9662
9593
|
const configDir = getConnectorConfigDir(name);
|
|
@@ -9753,7 +9684,7 @@ function saveApiKey(name, key, field) {
|
|
|
9753
9684
|
const keyField = field || guessKeyField(name);
|
|
9754
9685
|
if (keyField === "clientId" || keyField === "clientSecret") {
|
|
9755
9686
|
const credentialsFile = join3(configDir, "credentials.json");
|
|
9756
|
-
|
|
9687
|
+
mkdirSync(configDir, { recursive: true });
|
|
9757
9688
|
let creds = {};
|
|
9758
9689
|
if (existsSync3(credentialsFile)) {
|
|
9759
9690
|
try {
|
|
@@ -9761,7 +9692,7 @@ function saveApiKey(name, key, field) {
|
|
|
9761
9692
|
} catch {}
|
|
9762
9693
|
}
|
|
9763
9694
|
creds[keyField] = key;
|
|
9764
|
-
|
|
9695
|
+
writeFileSync(credentialsFile, JSON.stringify(creds, null, 2));
|
|
9765
9696
|
return;
|
|
9766
9697
|
}
|
|
9767
9698
|
const profileFile = join3(configDir, "profiles", `${profile}.json`);
|
|
@@ -9772,7 +9703,7 @@ function saveApiKey(name, key, field) {
|
|
|
9772
9703
|
config = JSON.parse(readFileSync3(profileFile, "utf-8"));
|
|
9773
9704
|
} catch {}
|
|
9774
9705
|
config[keyField] = key;
|
|
9775
|
-
|
|
9706
|
+
writeFileSync(profileFile, JSON.stringify(config, null, 2));
|
|
9776
9707
|
return;
|
|
9777
9708
|
}
|
|
9778
9709
|
if (existsSync3(profileDir)) {
|
|
@@ -9784,11 +9715,11 @@ function saveApiKey(name, key, field) {
|
|
|
9784
9715
|
} catch {}
|
|
9785
9716
|
}
|
|
9786
9717
|
config[keyField] = key;
|
|
9787
|
-
|
|
9718
|
+
writeFileSync(configFile, JSON.stringify(config, null, 2));
|
|
9788
9719
|
return;
|
|
9789
9720
|
}
|
|
9790
|
-
|
|
9791
|
-
|
|
9721
|
+
mkdirSync(profileDir, { recursive: true });
|
|
9722
|
+
writeFileSync(join3(profileDir, "config.json"), JSON.stringify({ [keyField]: key }, null, 2));
|
|
9792
9723
|
}
|
|
9793
9724
|
function guessKeyField(name) {
|
|
9794
9725
|
const docs = getConnectorDocs(name);
|
|
@@ -9889,9 +9820,9 @@ function saveOAuthTokens(name, tokens) {
|
|
|
9889
9820
|
const configDir = getConnectorConfigDir(name);
|
|
9890
9821
|
const profile = getCurrentProfile(name);
|
|
9891
9822
|
const profileDir = join3(configDir, "profiles", profile);
|
|
9892
|
-
|
|
9823
|
+
mkdirSync(profileDir, { recursive: true });
|
|
9893
9824
|
const tokensFile = join3(profileDir, "tokens.json");
|
|
9894
|
-
|
|
9825
|
+
writeFileSync(tokensFile, JSON.stringify(tokens, null, 2), { mode: 384 });
|
|
9895
9826
|
}
|
|
9896
9827
|
async function refreshOAuthToken(name) {
|
|
9897
9828
|
const oauthConfig = getOAuthConfig(name);
|
|
@@ -9951,8 +9882,8 @@ function listProfiles(name) {
|
|
|
9951
9882
|
}
|
|
9952
9883
|
function switchProfile(name, profile) {
|
|
9953
9884
|
const configDir = getConnectorConfigDir(name);
|
|
9954
|
-
|
|
9955
|
-
|
|
9885
|
+
mkdirSync(configDir, { recursive: true });
|
|
9886
|
+
writeFileSync(join3(configDir, "current_profile"), profile);
|
|
9956
9887
|
}
|
|
9957
9888
|
function deleteProfile(name, profile) {
|
|
9958
9889
|
if (profile === "default")
|
|
@@ -9961,7 +9892,7 @@ function deleteProfile(name, profile) {
|
|
|
9961
9892
|
const profilesDir = join3(configDir, "profiles");
|
|
9962
9893
|
const profileFile = join3(profilesDir, `${profile}.json`);
|
|
9963
9894
|
if (existsSync3(profileFile)) {
|
|
9964
|
-
|
|
9895
|
+
rmSync(profileFile);
|
|
9965
9896
|
if (getCurrentProfile(name) === profile) {
|
|
9966
9897
|
switchProfile(name, "default");
|
|
9967
9898
|
}
|
|
@@ -9969,7 +9900,7 @@ function deleteProfile(name, profile) {
|
|
|
9969
9900
|
}
|
|
9970
9901
|
const profileDir = join3(profilesDir, profile);
|
|
9971
9902
|
if (existsSync3(profileDir)) {
|
|
9972
|
-
|
|
9903
|
+
rmSync(profileDir, { recursive: true });
|
|
9973
9904
|
if (getCurrentProfile(name) === profile) {
|
|
9974
9905
|
switchProfile(name, "default");
|
|
9975
9906
|
}
|
|
@@ -10026,10 +9957,10 @@ var exports_serve = {};
|
|
|
10026
9957
|
__export(exports_serve, {
|
|
10027
9958
|
startServer: () => startServer
|
|
10028
9959
|
});
|
|
10029
|
-
import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync4, writeFileSync as
|
|
9960
|
+
import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
10030
9961
|
import { join as join5, dirname as dirname4, extname, basename } from "path";
|
|
10031
9962
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
10032
|
-
import { homedir as
|
|
9963
|
+
import { homedir as homedir2 } from "os";
|
|
10033
9964
|
function logActivity(action, connector, detail) {
|
|
10034
9965
|
activityLog.unshift({ action, connector, timestamp: Date.now(), detail });
|
|
10035
9966
|
if (activityLog.length > MAX_ACTIVITY_LOG) {
|
|
@@ -10270,10 +10201,7 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
10270
10201
|
if (!isValidConnectorName(name))
|
|
10271
10202
|
return json({ error: "Invalid connector name" }, 400, port);
|
|
10272
10203
|
try {
|
|
10273
|
-
|
|
10274
|
-
if (!removed) {
|
|
10275
|
-
return json({ error: `Connector '${name}' is not installed` }, 404, port);
|
|
10276
|
-
}
|
|
10204
|
+
removeConnector(name);
|
|
10277
10205
|
logActivity("uninstalled", name);
|
|
10278
10206
|
return json({ success: true, name }, 200, port);
|
|
10279
10207
|
} catch (e) {
|
|
@@ -10306,7 +10234,7 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
10306
10234
|
return json({ error: "Invalid connector name" }, 400, port);
|
|
10307
10235
|
try {
|
|
10308
10236
|
const profiles = listProfiles(name);
|
|
10309
|
-
const configDir = join5(
|
|
10237
|
+
const configDir = join5(homedir2(), ".connectors", name.startsWith("connect-") ? name : `connect-${name}`);
|
|
10310
10238
|
const currentProfileFile = join5(configDir, "current_profile");
|
|
10311
10239
|
let current = "default";
|
|
10312
10240
|
if (existsSync5(currentProfileFile)) {
|
|
@@ -10358,7 +10286,7 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
10358
10286
|
}
|
|
10359
10287
|
if (path === "/api/export" && method === "GET") {
|
|
10360
10288
|
try {
|
|
10361
|
-
const connectDir = join5(
|
|
10289
|
+
const connectDir = join5(homedir2(), ".connectors");
|
|
10362
10290
|
const result = {};
|
|
10363
10291
|
if (existsSync5(connectDir)) {
|
|
10364
10292
|
const entries = readdirSync3(connectDir, { withFileTypes: true });
|
|
@@ -10418,7 +10346,7 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
10418
10346
|
return json({ error: "Invalid import format: missing 'connectors' object" }, 400, port);
|
|
10419
10347
|
}
|
|
10420
10348
|
let imported = 0;
|
|
10421
|
-
const connectDir = join5(
|
|
10349
|
+
const connectDir = join5(homedir2(), ".connectors");
|
|
10422
10350
|
for (const [connectorName, data] of Object.entries(body.connectors)) {
|
|
10423
10351
|
if (!isValidConnectorName(connectorName))
|
|
10424
10352
|
continue;
|
|
@@ -10429,9 +10357,9 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
10429
10357
|
for (const [profileName, config] of Object.entries(data.profiles)) {
|
|
10430
10358
|
if (!config || typeof config !== "object")
|
|
10431
10359
|
continue;
|
|
10432
|
-
|
|
10360
|
+
mkdirSync2(profilesDir, { recursive: true });
|
|
10433
10361
|
const profileFile = join5(profilesDir, `${profileName}.json`);
|
|
10434
|
-
|
|
10362
|
+
writeFileSync2(profileFile, JSON.stringify(config, null, 2));
|
|
10435
10363
|
imported++;
|
|
10436
10364
|
}
|
|
10437
10365
|
}
|
|
@@ -12034,8 +11962,8 @@ function App({ initialConnectors, overwrite = false }) {
|
|
|
12034
11962
|
init_registry();
|
|
12035
11963
|
init_installer();
|
|
12036
11964
|
init_auth();
|
|
12037
|
-
import { readdirSync as readdirSync4, existsSync as existsSync6, statSync as statSync3, readFileSync as readFileSync5, writeFileSync as
|
|
12038
|
-
import { homedir as
|
|
11965
|
+
import { readdirSync as readdirSync4, existsSync as existsSync6, statSync as statSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
|
|
11966
|
+
import { homedir as homedir3 } from "os";
|
|
12039
11967
|
import { join as join6, relative } from "path";
|
|
12040
11968
|
|
|
12041
11969
|
// src/lib/test-endpoints.ts
|
|
@@ -12381,7 +12309,7 @@ var PRESETS = {
|
|
|
12381
12309
|
commerce: { description: "Commerce and finance", connectors: ["stripe", "shopify", "revolut", "mercury", "pandadoc"] }
|
|
12382
12310
|
};
|
|
12383
12311
|
var program2 = new Command;
|
|
12384
|
-
program2.name("connectors").description("Install API connectors for your project").version("1.1.
|
|
12312
|
+
program2.name("connectors").description("Install API connectors for your project").version("1.1.9").enablePositionalOptions();
|
|
12385
12313
|
program2.command("interactive", { isDefault: true }).alias("i").description("Interactive connector browser").action(() => {
|
|
12386
12314
|
if (!isTTY) {
|
|
12387
12315
|
console.log(`Non-interactive environment detected. Use a subcommand:
|
|
@@ -12411,7 +12339,7 @@ function listFilesRecursive(dir, base = dir) {
|
|
|
12411
12339
|
}
|
|
12412
12340
|
return files;
|
|
12413
12341
|
}
|
|
12414
|
-
program2.command("install").alias("add").argument("[connectors...]", "Connectors to
|
|
12342
|
+
program2.command("install").alias("add").argument("[connectors...]", "Connectors to verify").option("-c, --category <category>", "Verify all connectors in a category").option("--preset <preset>", "Verify a preset bundle (e.g. ai, fullstack, google)").option("--json", "Output results as JSON", false).description("Verify connectors are available in the global package").action((connectors, options) => {
|
|
12415
12343
|
if (options.category) {
|
|
12416
12344
|
const category = CATEGORIES.find((c) => c.toLowerCase() === options.category.toLowerCase());
|
|
12417
12345
|
if (!category) {
|
|
@@ -12424,8 +12352,7 @@ program2.command("install").alias("add").argument("[connectors...]", "Connectors
|
|
|
12424
12352
|
process.exit(1);
|
|
12425
12353
|
return;
|
|
12426
12354
|
}
|
|
12427
|
-
|
|
12428
|
-
connectors.push(...categoryConnectors);
|
|
12355
|
+
connectors.push(...getConnectorsByCategory(category).map((c) => c.name));
|
|
12429
12356
|
}
|
|
12430
12357
|
if (options.preset) {
|
|
12431
12358
|
const preset = PRESETS[options.preset.toLowerCase()];
|
|
@@ -12443,133 +12370,25 @@ program2.command("install").alias("add").argument("[connectors...]", "Connectors
|
|
|
12443
12370
|
}
|
|
12444
12371
|
if (connectors.length === 0) {
|
|
12445
12372
|
if (!isTTY) {
|
|
12446
|
-
console.error("Error: specify connectors to
|
|
12373
|
+
console.error("Error: specify connectors to verify. Example: connectors install figma stripe");
|
|
12447
12374
|
process.exit(1);
|
|
12448
12375
|
}
|
|
12449
12376
|
render(/* @__PURE__ */ jsxDEV7(App, {}, undefined, false, undefined, this));
|
|
12450
12377
|
return;
|
|
12451
12378
|
}
|
|
12452
|
-
|
|
12453
|
-
const installed = getInstalledConnectors();
|
|
12454
|
-
const destDir = join6(process.cwd(), ".connectors");
|
|
12455
|
-
const actions = [];
|
|
12456
|
-
for (const name of connectors) {
|
|
12457
|
-
if (!/^[a-z0-9-]+$/.test(name)) {
|
|
12458
|
-
actions.push({ connector: name, action: "error", reason: `Invalid connector name '${name}'` });
|
|
12459
|
-
continue;
|
|
12460
|
-
}
|
|
12461
|
-
const meta = getConnector(name);
|
|
12462
|
-
if (!meta) {
|
|
12463
|
-
actions.push({ connector: name, action: "error", reason: `Connector '${name}' not found in registry` });
|
|
12464
|
-
continue;
|
|
12465
|
-
}
|
|
12466
|
-
if (!connectorExists(name)) {
|
|
12467
|
-
actions.push({ connector: name, action: "error", reason: `Connector '${name}' source files not found` });
|
|
12468
|
-
continue;
|
|
12469
|
-
}
|
|
12470
|
-
const connectorDirName = name.startsWith("connect-") ? name : `connect-${name}`;
|
|
12471
|
-
const sourcePath = getConnectorPath(name);
|
|
12472
|
-
const destPath = join6(destDir, connectorDirName);
|
|
12473
|
-
const alreadyInstalled = installed.includes(name);
|
|
12474
|
-
const files = listFilesRecursive(sourcePath);
|
|
12475
|
-
const importLine = `export * as ${name} from './${connectorDirName}/src/index.js';`;
|
|
12476
|
-
if (alreadyInstalled && !options.overwrite) {
|
|
12477
|
-
actions.push({
|
|
12478
|
-
connector: name,
|
|
12479
|
-
action: "skip",
|
|
12480
|
-
reason: "Already installed. Use --overwrite to replace.",
|
|
12481
|
-
sourcePath,
|
|
12482
|
-
destPath
|
|
12483
|
-
});
|
|
12484
|
-
} else {
|
|
12485
|
-
actions.push({
|
|
12486
|
-
connector: name,
|
|
12487
|
-
action: alreadyInstalled ? "overwrite" : "install",
|
|
12488
|
-
sourcePath,
|
|
12489
|
-
destPath,
|
|
12490
|
-
files,
|
|
12491
|
-
importLine
|
|
12492
|
-
});
|
|
12493
|
-
}
|
|
12494
|
-
}
|
|
12495
|
-
if (options.json) {
|
|
12496
|
-
console.log(JSON.stringify({ dryRun: true, actions }, null, 2));
|
|
12497
|
-
process.exit(actions.every((a) => a.action !== "error") ? 0 : 1);
|
|
12498
|
-
return;
|
|
12499
|
-
}
|
|
12500
|
-
console.log(chalk2.bold(`
|
|
12501
|
-
Dry run \u2014 no changes will be made
|
|
12502
|
-
`));
|
|
12503
|
-
for (const a of actions) {
|
|
12504
|
-
if (a.action === "error") {
|
|
12505
|
-
console.log(chalk2.red(` \u2717 ${a.connector}: ${a.reason}`));
|
|
12506
|
-
continue;
|
|
12507
|
-
}
|
|
12508
|
-
if (a.action === "skip") {
|
|
12509
|
-
console.log(chalk2.yellow(` \u2298 ${a.connector}: ${a.reason}`));
|
|
12510
|
-
continue;
|
|
12511
|
-
}
|
|
12512
|
-
const actionLabel = a.action === "overwrite" ? chalk2.yellow("overwrite") : chalk2.green("install");
|
|
12513
|
-
console.log(` ${actionLabel} ${chalk2.cyan(a.connector)}`);
|
|
12514
|
-
console.log(chalk2.dim(` source: ${a.sourcePath}`));
|
|
12515
|
-
console.log(chalk2.dim(` dest: ${a.destPath}`));
|
|
12516
|
-
if (a.files && a.files.length > 0) {
|
|
12517
|
-
console.log(chalk2.dim(` files (${a.files.length}):`));
|
|
12518
|
-
for (const f of a.files) {
|
|
12519
|
-
console.log(chalk2.dim(` ${f}`));
|
|
12520
|
-
}
|
|
12521
|
-
}
|
|
12522
|
-
if (a.importLine) {
|
|
12523
|
-
console.log(` ${chalk2.dim("index.ts:")} ${a.importLine}`);
|
|
12524
|
-
}
|
|
12525
|
-
console.log();
|
|
12526
|
-
}
|
|
12527
|
-
const installCount = actions.filter((a) => a.action === "install").length;
|
|
12528
|
-
const overwriteCount = actions.filter((a) => a.action === "overwrite").length;
|
|
12529
|
-
const skipCount = actions.filter((a) => a.action === "skip").length;
|
|
12530
|
-
const errorCount = actions.filter((a) => a.action === "error").length;
|
|
12531
|
-
const parts = [];
|
|
12532
|
-
if (installCount)
|
|
12533
|
-
parts.push(chalk2.green(`${installCount} to install`));
|
|
12534
|
-
if (overwriteCount)
|
|
12535
|
-
parts.push(chalk2.yellow(`${overwriteCount} to overwrite`));
|
|
12536
|
-
if (skipCount)
|
|
12537
|
-
parts.push(chalk2.yellow(`${skipCount} skipped`));
|
|
12538
|
-
if (errorCount)
|
|
12539
|
-
parts.push(chalk2.red(`${errorCount} failed`));
|
|
12540
|
-
console.log(` ${chalk2.bold("Summary:")} ${parts.join(", ")}`);
|
|
12541
|
-
console.log(chalk2.dim(`
|
|
12542
|
-
Run without --dry-run to apply.
|
|
12543
|
-
`));
|
|
12544
|
-
process.exit(errorCount > 0 ? 1 : 0);
|
|
12545
|
-
return;
|
|
12546
|
-
}
|
|
12547
|
-
const results = connectors.map((name) => installConnector(name, { overwrite: options.overwrite }));
|
|
12379
|
+
const results = connectors.map((name) => installConnector(name));
|
|
12548
12380
|
if (options.json) {
|
|
12549
12381
|
console.log(JSON.stringify(results, null, 2));
|
|
12550
12382
|
process.exit(results.every((r) => r.success) ? 0 : 1);
|
|
12551
12383
|
return;
|
|
12552
12384
|
}
|
|
12553
|
-
console.log(chalk2.bold(`
|
|
12554
|
-
Installing connectors...
|
|
12555
|
-
`));
|
|
12556
|
-
const succeeded = [];
|
|
12557
12385
|
for (const result of results) {
|
|
12558
12386
|
if (result.success) {
|
|
12559
|
-
console.log(chalk2.green(`\u2713 ${result.connector}`));
|
|
12560
|
-
succeeded.push(result.connector);
|
|
12387
|
+
console.log(chalk2.green(`\u2713 ${result.connector}`) + chalk2.dim(` \u2014 available at ${result.path}`));
|
|
12561
12388
|
} else {
|
|
12562
12389
|
console.log(chalk2.red(`\u2717 ${result.connector}: ${result.error}`));
|
|
12563
12390
|
}
|
|
12564
12391
|
}
|
|
12565
|
-
if (succeeded.length > 0) {
|
|
12566
|
-
console.log(chalk2.bold(`
|
|
12567
|
-
Next steps:`));
|
|
12568
|
-
const importNames = succeeded.join(", ");
|
|
12569
|
-
console.log(chalk2.dim(` 1. Import: `) + `import { ${importNames} } from './.connectors'`);
|
|
12570
|
-
console.log(chalk2.dim(` 2. Set key: `) + `connectors docs ${succeeded[0]}` + chalk2.dim(` (see env vars)`));
|
|
12571
|
-
console.log(chalk2.dim(` 3. Explore: `) + `connectors serve` + chalk2.dim(` (dashboard for auth management)`));
|
|
12572
|
-
}
|
|
12573
12392
|
process.exit(results.every((r) => r.success) ? 0 : 1);
|
|
12574
12393
|
});
|
|
12575
12394
|
program2.command("list").alias("ls").option("-c, --category <category>", "Filter by category").option("-a, --all", "Show all available connectors", false).option("-i, --installed", "Show only installed connectors", false).option("-b, --brief", "Output only connector names", false).option("--json", "Output as JSON", false).description("List available or installed connectors").action((options) => {
|
|
@@ -12973,7 +12792,7 @@ Updating ${toUpdate.length} connector(s)...
|
|
|
12973
12792
|
});
|
|
12974
12793
|
program2.command("status").option("--json", "Output as JSON", false).description("Show auth status of all configured connectors (project + global)").action((options) => {
|
|
12975
12794
|
const installed = getInstalledConnectors();
|
|
12976
|
-
const configDir = join6(
|
|
12795
|
+
const configDir = join6(homedir3(), ".connectors");
|
|
12977
12796
|
const seen = new Set;
|
|
12978
12797
|
const allStatuses = [];
|
|
12979
12798
|
function buildStatusEntry(name, source) {
|
|
@@ -13390,7 +13209,7 @@ program2.command("init").option("--json", "Output presets and suggestions as JSO
|
|
|
13390
13209
|
{ key: "commerce", emoji: "\uD83D\uDCB3", label: "Commerce", connectors: ["stripe", "shopify", "paypal", "revolut", "mercury"], description: "Commerce and finance" },
|
|
13391
13210
|
{ key: "google", emoji: "\uD83D\uDCC1", label: "Google Workspace", connectors: ["gmail", "googledrive", "googlecalendar", "googledocs", "googlesheets"], description: "Google Workspace suite" }
|
|
13392
13211
|
];
|
|
13393
|
-
const connectorsHome = join6(
|
|
13212
|
+
const connectorsHome = join6(homedir3(), ".connectors");
|
|
13394
13213
|
let configuredCount = 0;
|
|
13395
13214
|
const configuredNames = [];
|
|
13396
13215
|
try {
|
|
@@ -13496,7 +13315,7 @@ function redactSecrets(obj) {
|
|
|
13496
13315
|
return obj;
|
|
13497
13316
|
}
|
|
13498
13317
|
program2.command("export").option("-o, --output <file>", "Write to file instead of stdout").option("--include-secrets", "Include secrets in plaintext (dangerous \u2014 use only for backup/restore)").description("Export all connector credentials as JSON backup").action((options) => {
|
|
13499
|
-
const connectDir = join6(
|
|
13318
|
+
const connectDir = join6(homedir3(), ".connectors");
|
|
13500
13319
|
const result = {};
|
|
13501
13320
|
if (existsSync6(connectDir)) {
|
|
13502
13321
|
for (const entry of readdirSync4(connectDir)) {
|
|
@@ -13554,7 +13373,7 @@ program2.command("export").option("-o, --output <file>", "Write to file instead
|
|
|
13554
13373
|
}
|
|
13555
13374
|
const exportData = JSON.stringify(exportPayload, null, 2);
|
|
13556
13375
|
if (options.output) {
|
|
13557
|
-
|
|
13376
|
+
writeFileSync3(options.output, exportData);
|
|
13558
13377
|
console.log(chalk2.green(`\u2713 Exported to ${options.output}`));
|
|
13559
13378
|
} else {
|
|
13560
13379
|
console.log(exportData);
|
|
@@ -13600,15 +13419,15 @@ program2.command("import").argument("<file>", "JSON backup file to import (use -
|
|
|
13600
13419
|
process.exit(1);
|
|
13601
13420
|
return;
|
|
13602
13421
|
}
|
|
13603
|
-
const connectDir = join6(
|
|
13422
|
+
const connectDir = join6(homedir3(), ".connectors");
|
|
13604
13423
|
let imported = 0;
|
|
13605
13424
|
for (const [connectorName, connData] of Object.entries(data.connectors)) {
|
|
13606
13425
|
if (!/^[a-z0-9-]+$/.test(connectorName))
|
|
13607
13426
|
continue;
|
|
13608
13427
|
const connectorDir = join6(connectDir, `connect-${connectorName}`);
|
|
13609
13428
|
if (connData.credentials && typeof connData.credentials === "object") {
|
|
13610
|
-
|
|
13611
|
-
|
|
13429
|
+
mkdirSync3(connectorDir, { recursive: true });
|
|
13430
|
+
writeFileSync3(join6(connectorDir, "credentials.json"), JSON.stringify(connData.credentials, null, 2));
|
|
13612
13431
|
imported++;
|
|
13613
13432
|
}
|
|
13614
13433
|
if (!connData.profiles || typeof connData.profiles !== "object")
|
|
@@ -13617,8 +13436,8 @@ program2.command("import").argument("<file>", "JSON backup file to import (use -
|
|
|
13617
13436
|
for (const [profileName, config] of Object.entries(connData.profiles)) {
|
|
13618
13437
|
if (!config || typeof config !== "object")
|
|
13619
13438
|
continue;
|
|
13620
|
-
|
|
13621
|
-
|
|
13439
|
+
mkdirSync3(profilesDir, { recursive: true });
|
|
13440
|
+
writeFileSync3(join6(profilesDir, `${profileName}.json`), JSON.stringify(config, null, 2));
|
|
13622
13441
|
imported++;
|
|
13623
13442
|
}
|
|
13624
13443
|
}
|
|
@@ -13629,8 +13448,8 @@ program2.command("import").argument("<file>", "JSON backup file to import (use -
|
|
|
13629
13448
|
}
|
|
13630
13449
|
});
|
|
13631
13450
|
program2.command("auth-import").option("--json", "Output as JSON", false).option("-d, --dry-run", "Preview what would be imported without copying", false).option("--force", "Overwrite existing files in ~/.connectors/", false).description("Migrate auth tokens from ~/.connect/ to ~/.connectors/").action((options) => {
|
|
13632
|
-
const oldBase = join6(
|
|
13633
|
-
const newBase = join6(
|
|
13451
|
+
const oldBase = join6(homedir3(), ".connect");
|
|
13452
|
+
const newBase = join6(homedir3(), ".connectors");
|
|
13634
13453
|
if (!existsSync6(oldBase)) {
|
|
13635
13454
|
if (options.json) {
|
|
13636
13455
|
console.log(JSON.stringify({ imported: [], skipped: [], error: null, message: "No ~/.connect/ directory found" }));
|
|
@@ -13679,9 +13498,9 @@ program2.command("auth-import").option("--json", "Output as JSON", false).option
|
|
|
13679
13498
|
}
|
|
13680
13499
|
if (!options.dryRun) {
|
|
13681
13500
|
const parentDir = join6(destPath, "..");
|
|
13682
|
-
|
|
13501
|
+
mkdirSync3(parentDir, { recursive: true });
|
|
13683
13502
|
const content = readFileSync5(srcPath);
|
|
13684
|
-
|
|
13503
|
+
writeFileSync3(destPath, content);
|
|
13685
13504
|
}
|
|
13686
13505
|
copiedFiles.push(relFile);
|
|
13687
13506
|
}
|
|
@@ -13926,7 +13745,7 @@ program2.command("env").option("-o, --output <file>", "Write to file instead of
|
|
|
13926
13745
|
`) + `
|
|
13927
13746
|
`;
|
|
13928
13747
|
if (options.output) {
|
|
13929
|
-
|
|
13748
|
+
writeFileSync3(options.output, output);
|
|
13930
13749
|
console.log(chalk2.green(`\u2713 Written to ${options.output} (${vars.length} variables)`));
|
|
13931
13750
|
} else {
|
|
13932
13751
|
console.log(output);
|
|
@@ -13954,7 +13773,7 @@ Available presets:
|
|
|
13954
13773
|
`));
|
|
13955
13774
|
});
|
|
13956
13775
|
program2.command("whoami").option("--json", "Output as JSON", false).description("Show current setup: config dir, installed connectors, auth status").action((options) => {
|
|
13957
|
-
const configDir = join6(
|
|
13776
|
+
const configDir = join6(homedir3(), ".connectors");
|
|
13958
13777
|
const installed = getInstalledConnectors();
|
|
13959
13778
|
const version = "0.3.1";
|
|
13960
13779
|
let configured = 0;
|
|
@@ -14115,7 +13934,7 @@ Testing connector credentials...
|
|
|
14115
13934
|
}
|
|
14116
13935
|
}
|
|
14117
13936
|
if (!apiKey) {
|
|
14118
|
-
const connectorConfigDir = join6(
|
|
13937
|
+
const connectorConfigDir = join6(homedir3(), ".connectors", name.startsWith("connect-") ? name : `connect-${name}`);
|
|
14119
13938
|
let currentProfile = "default";
|
|
14120
13939
|
const currentProfileFile = join6(connectorConfigDir, "current_profile");
|
|
14121
13940
|
if (existsSync6(currentProfileFile)) {
|
package/bin/mcp.js
CHANGED
|
@@ -25351,8 +25351,7 @@ function loadConnectorVersions() {
|
|
|
25351
25351
|
}
|
|
25352
25352
|
|
|
25353
25353
|
// src/lib/installer.ts
|
|
25354
|
-
import { existsSync as existsSync2,
|
|
25355
|
-
import { homedir } from "os";
|
|
25354
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync, statSync } from "fs";
|
|
25356
25355
|
import { join as join2, dirname as dirname2 } from "path";
|
|
25357
25356
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
25358
25357
|
var __dirname2 = dirname2(fileURLToPath2(import.meta.url));
|
|
@@ -25371,7 +25370,6 @@ function getConnectorPath(name) {
|
|
|
25371
25370
|
return join2(CONNECTORS_DIR, connectorName);
|
|
25372
25371
|
}
|
|
25373
25372
|
function installConnector(name, options = {}) {
|
|
25374
|
-
const { targetDir = process.cwd(), overwrite = false } = options;
|
|
25375
25373
|
if (!/^[a-z0-9-]+$/.test(name)) {
|
|
25376
25374
|
return {
|
|
25377
25375
|
connector: name,
|
|
@@ -25379,10 +25377,7 @@ function installConnector(name, options = {}) {
|
|
|
25379
25377
|
error: `Invalid connector name '${name}'`
|
|
25380
25378
|
};
|
|
25381
25379
|
}
|
|
25382
|
-
const connectorName = name.startsWith("connect-") ? name : `connect-${name}`;
|
|
25383
25380
|
const sourcePath = getConnectorPath(name);
|
|
25384
|
-
const destDir = join2(targetDir, ".connectors");
|
|
25385
|
-
const destPath = join2(destDir, connectorName);
|
|
25386
25381
|
if (!existsSync2(sourcePath)) {
|
|
25387
25382
|
return {
|
|
25388
25383
|
connector: name,
|
|
@@ -25390,71 +25385,18 @@ function installConnector(name, options = {}) {
|
|
|
25390
25385
|
error: `Connector '${name}' not found`
|
|
25391
25386
|
};
|
|
25392
25387
|
}
|
|
25393
|
-
|
|
25394
|
-
|
|
25395
|
-
|
|
25396
|
-
|
|
25397
|
-
|
|
25398
|
-
path: destPath
|
|
25399
|
-
};
|
|
25400
|
-
}
|
|
25401
|
-
try {
|
|
25402
|
-
if (!existsSync2(destDir)) {
|
|
25403
|
-
mkdirSync(destDir, { recursive: true });
|
|
25404
|
-
}
|
|
25405
|
-
cpSync(sourcePath, destPath, { recursive: true });
|
|
25406
|
-
const homeCredDir = join2(homedir(), ".connectors", connectorName);
|
|
25407
|
-
if (existsSync2(homeCredDir)) {
|
|
25408
|
-
const filesToCopy = ["credentials.json", "current_profile"];
|
|
25409
|
-
for (const file of filesToCopy) {
|
|
25410
|
-
const src = join2(homeCredDir, file);
|
|
25411
|
-
if (existsSync2(src)) {
|
|
25412
|
-
cpSync(src, join2(destPath, file));
|
|
25413
|
-
}
|
|
25414
|
-
}
|
|
25415
|
-
const profilesDir = join2(homeCredDir, "profiles");
|
|
25416
|
-
if (existsSync2(profilesDir)) {
|
|
25417
|
-
cpSync(profilesDir, join2(destPath, "profiles"), { recursive: true });
|
|
25418
|
-
}
|
|
25419
|
-
}
|
|
25420
|
-
updateConnectorsIndex(destDir);
|
|
25421
|
-
return {
|
|
25422
|
-
connector: name,
|
|
25423
|
-
success: true,
|
|
25424
|
-
path: destPath
|
|
25425
|
-
};
|
|
25426
|
-
} catch (error2) {
|
|
25427
|
-
return {
|
|
25428
|
-
connector: name,
|
|
25429
|
-
success: false,
|
|
25430
|
-
error: error2 instanceof Error ? error2.message : "Unknown error"
|
|
25431
|
-
};
|
|
25432
|
-
}
|
|
25433
|
-
}
|
|
25434
|
-
function updateConnectorsIndex(connectorsDir) {
|
|
25435
|
-
const indexPath = join2(connectorsDir, "index.ts");
|
|
25436
|
-
const connectors = readdirSync(connectorsDir).filter((f) => f.startsWith("connect-") && !f.includes("."));
|
|
25437
|
-
const exports = connectors.map((c) => {
|
|
25438
|
-
const name = c.replace("connect-", "");
|
|
25439
|
-
return `export * as ${name} from './${c}/src/index.js';`;
|
|
25440
|
-
}).join(`
|
|
25441
|
-
`);
|
|
25442
|
-
const content = `/**
|
|
25443
|
-
* Auto-generated index of installed connectors
|
|
25444
|
-
* Do not edit manually - run 'connectors install' to update
|
|
25445
|
-
*/
|
|
25446
|
-
|
|
25447
|
-
${exports}
|
|
25448
|
-
`;
|
|
25449
|
-
writeFileSync(indexPath, content);
|
|
25388
|
+
return {
|
|
25389
|
+
connector: name,
|
|
25390
|
+
success: true,
|
|
25391
|
+
path: sourcePath
|
|
25392
|
+
};
|
|
25450
25393
|
}
|
|
25451
|
-
function getInstalledConnectors(
|
|
25452
|
-
|
|
25453
|
-
if (!existsSync2(connectorsDir)) {
|
|
25394
|
+
function getInstalledConnectors() {
|
|
25395
|
+
if (!existsSync2(CONNECTORS_DIR)) {
|
|
25454
25396
|
return [];
|
|
25455
25397
|
}
|
|
25456
|
-
return readdirSync(
|
|
25457
|
-
const fullPath = join2(
|
|
25398
|
+
return readdirSync(CONNECTORS_DIR).filter((f) => {
|
|
25399
|
+
const fullPath = join2(CONNECTORS_DIR, f);
|
|
25458
25400
|
return f.startsWith("connect-") && statSync(fullPath).isDirectory();
|
|
25459
25401
|
}).map((f) => f.replace("connect-", ""));
|
|
25460
25402
|
}
|
|
@@ -25500,21 +25442,13 @@ function parseEnvVarsTable(section) {
|
|
|
25500
25442
|
}
|
|
25501
25443
|
return vars;
|
|
25502
25444
|
}
|
|
25503
|
-
function removeConnector(name
|
|
25504
|
-
|
|
25505
|
-
const connectorsDir = join2(targetDir, ".connectors");
|
|
25506
|
-
const connectorPath = join2(connectorsDir, connectorName);
|
|
25507
|
-
if (!existsSync2(connectorPath)) {
|
|
25508
|
-
return false;
|
|
25509
|
-
}
|
|
25510
|
-
rmSync(connectorPath, { recursive: true });
|
|
25511
|
-
updateConnectorsIndex(connectorsDir);
|
|
25512
|
-
return true;
|
|
25445
|
+
function removeConnector(name) {
|
|
25446
|
+
return false;
|
|
25513
25447
|
}
|
|
25514
25448
|
|
|
25515
25449
|
// src/server/auth.ts
|
|
25516
|
-
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync
|
|
25517
|
-
import { homedir
|
|
25450
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync, mkdirSync, readdirSync as readdirSync2, rmSync, statSync as statSync2 } from "fs";
|
|
25451
|
+
import { homedir } from "os";
|
|
25518
25452
|
import { join as join3 } from "path";
|
|
25519
25453
|
var oauthStateStore = new Map;
|
|
25520
25454
|
var GOOGLE_SCOPES = {
|
|
@@ -25568,7 +25502,7 @@ function getAuthType(name) {
|
|
|
25568
25502
|
}
|
|
25569
25503
|
function getConnectorConfigDir(name) {
|
|
25570
25504
|
const connectorName = name.startsWith("connect-") ? name : `connect-${name}`;
|
|
25571
|
-
return join3(
|
|
25505
|
+
return join3(homedir(), ".connectors", connectorName);
|
|
25572
25506
|
}
|
|
25573
25507
|
function getCurrentProfile(name) {
|
|
25574
25508
|
const configDir = getConnectorConfigDir(name);
|
|
@@ -25661,7 +25595,7 @@ function saveApiKey(name, key, field) {
|
|
|
25661
25595
|
const keyField = field || guessKeyField(name);
|
|
25662
25596
|
if (keyField === "clientId" || keyField === "clientSecret") {
|
|
25663
25597
|
const credentialsFile = join3(configDir, "credentials.json");
|
|
25664
|
-
|
|
25598
|
+
mkdirSync(configDir, { recursive: true });
|
|
25665
25599
|
let creds = {};
|
|
25666
25600
|
if (existsSync3(credentialsFile)) {
|
|
25667
25601
|
try {
|
|
@@ -25669,7 +25603,7 @@ function saveApiKey(name, key, field) {
|
|
|
25669
25603
|
} catch {}
|
|
25670
25604
|
}
|
|
25671
25605
|
creds[keyField] = key;
|
|
25672
|
-
|
|
25606
|
+
writeFileSync(credentialsFile, JSON.stringify(creds, null, 2));
|
|
25673
25607
|
return;
|
|
25674
25608
|
}
|
|
25675
25609
|
const profileFile = join3(configDir, "profiles", `${profile}.json`);
|
|
@@ -25680,7 +25614,7 @@ function saveApiKey(name, key, field) {
|
|
|
25680
25614
|
config2 = JSON.parse(readFileSync3(profileFile, "utf-8"));
|
|
25681
25615
|
} catch {}
|
|
25682
25616
|
config2[keyField] = key;
|
|
25683
|
-
|
|
25617
|
+
writeFileSync(profileFile, JSON.stringify(config2, null, 2));
|
|
25684
25618
|
return;
|
|
25685
25619
|
}
|
|
25686
25620
|
if (existsSync3(profileDir)) {
|
|
@@ -25692,11 +25626,11 @@ function saveApiKey(name, key, field) {
|
|
|
25692
25626
|
} catch {}
|
|
25693
25627
|
}
|
|
25694
25628
|
config2[keyField] = key;
|
|
25695
|
-
|
|
25629
|
+
writeFileSync(configFile, JSON.stringify(config2, null, 2));
|
|
25696
25630
|
return;
|
|
25697
25631
|
}
|
|
25698
|
-
|
|
25699
|
-
|
|
25632
|
+
mkdirSync(profileDir, { recursive: true });
|
|
25633
|
+
writeFileSync(join3(profileDir, "config.json"), JSON.stringify({ [keyField]: key }, null, 2));
|
|
25700
25634
|
}
|
|
25701
25635
|
function guessKeyField(name) {
|
|
25702
25636
|
const docs = getConnectorDocs(name);
|
|
@@ -25849,7 +25783,7 @@ async function getConnectorCommandHelp(name, command) {
|
|
|
25849
25783
|
loadConnectorVersions();
|
|
25850
25784
|
var server = new McpServer({
|
|
25851
25785
|
name: "connectors",
|
|
25852
|
-
version: "1.1.
|
|
25786
|
+
version: "1.1.9"
|
|
25853
25787
|
});
|
|
25854
25788
|
server.registerTool("search_connectors", {
|
|
25855
25789
|
title: "Search Connectors",
|
|
@@ -25947,14 +25881,14 @@ server.registerTool("connector_docs", {
|
|
|
25947
25881
|
});
|
|
25948
25882
|
server.registerTool("install_connector", {
|
|
25949
25883
|
title: "Install Connector",
|
|
25950
|
-
description: "
|
|
25884
|
+
description: "Verify connectors are available in the global package.",
|
|
25951
25885
|
inputSchema: {
|
|
25952
25886
|
names: exports_external.array(exports_external.string()),
|
|
25953
25887
|
overwrite: exports_external.boolean().optional()
|
|
25954
25888
|
}
|
|
25955
|
-
}, async ({ names
|
|
25956
|
-
const results = names.map((name) => installConnector(name
|
|
25957
|
-
const summary = results.map((r) => r.success ? `\u2713 ${r.connector}
|
|
25889
|
+
}, async ({ names }) => {
|
|
25890
|
+
const results = names.map((name) => installConnector(name));
|
|
25891
|
+
const summary = results.map((r) => r.success ? `\u2713 ${r.connector} available at ${r.path}` : `\u2717 ${r.connector}: ${r.error}`);
|
|
25958
25892
|
return {
|
|
25959
25893
|
content: [
|
|
25960
25894
|
{
|
|
@@ -25962,8 +25896,7 @@ server.registerTool("install_connector", {
|
|
|
25962
25896
|
text: JSON.stringify({
|
|
25963
25897
|
results,
|
|
25964
25898
|
summary: summary.join(`
|
|
25965
|
-
`)
|
|
25966
|
-
usage: results.some((r) => r.success) ? "Import from './.connectors': import { " + results.filter((r) => r.success).map((r) => r.connector).join(", ") + " } from './.connectors'" : undefined
|
|
25899
|
+
`)
|
|
25967
25900
|
}, null, 2)
|
|
25968
25901
|
}
|
|
25969
25902
|
]
|
|
@@ -25971,22 +25904,22 @@ server.registerTool("install_connector", {
|
|
|
25971
25904
|
});
|
|
25972
25905
|
server.registerTool("remove_connector", {
|
|
25973
25906
|
title: "Remove Connector",
|
|
25974
|
-
description: "Remove
|
|
25907
|
+
description: "Remove connector auth/credentials from ~/.connectors/. Does not remove the connector from the global package.",
|
|
25975
25908
|
inputSchema: { name: exports_external.string() }
|
|
25976
25909
|
}, async ({ name }) => {
|
|
25977
|
-
|
|
25910
|
+
removeConnector(name);
|
|
25978
25911
|
return {
|
|
25979
25912
|
content: [
|
|
25980
25913
|
{
|
|
25981
25914
|
type: "text",
|
|
25982
|
-
text: JSON.stringify({ name,
|
|
25915
|
+
text: JSON.stringify({ name, message: "Connector auth can be cleared with configure_auth. The connector itself is part of the global package." })
|
|
25983
25916
|
}
|
|
25984
25917
|
]
|
|
25985
25918
|
};
|
|
25986
25919
|
});
|
|
25987
25920
|
server.registerTool("list_installed", {
|
|
25988
25921
|
title: "List Installed Connectors",
|
|
25989
|
-
description: "List connectors
|
|
25922
|
+
description: "List all connectors available in the global package.",
|
|
25990
25923
|
inputSchema: {}
|
|
25991
25924
|
}, async () => {
|
|
25992
25925
|
const installed = getInstalledConnectors();
|
package/bin/serve.js
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
var __require = import.meta.require;
|
|
4
4
|
|
|
5
5
|
// src/server/serve.ts
|
|
6
|
-
import { existsSync as existsSync4, readdirSync as readdirSync3, readFileSync as readFileSync4, writeFileSync as
|
|
6
|
+
import { existsSync as existsSync4, readdirSync as readdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
7
7
|
import { join as join4, dirname as dirname3, extname, basename } from "path";
|
|
8
8
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
9
|
-
import { homedir as
|
|
9
|
+
import { homedir as homedir2 } from "os";
|
|
10
10
|
|
|
11
11
|
// src/lib/registry.ts
|
|
12
12
|
import { existsSync, readFileSync } from "fs";
|
|
@@ -5943,8 +5943,7 @@ function loadConnectorVersions() {
|
|
|
5943
5943
|
}
|
|
5944
5944
|
|
|
5945
5945
|
// src/lib/installer.ts
|
|
5946
|
-
import { existsSync as existsSync2,
|
|
5947
|
-
import { homedir } from "os";
|
|
5946
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync, statSync } from "fs";
|
|
5948
5947
|
import { join as join2, dirname as dirname2 } from "path";
|
|
5949
5948
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5950
5949
|
var __dirname2 = dirname2(fileURLToPath2(import.meta.url));
|
|
@@ -5963,7 +5962,6 @@ function getConnectorPath(name) {
|
|
|
5963
5962
|
return join2(CONNECTORS_DIR, connectorName);
|
|
5964
5963
|
}
|
|
5965
5964
|
function installConnector(name, options = {}) {
|
|
5966
|
-
const { targetDir = process.cwd(), overwrite = false } = options;
|
|
5967
5965
|
if (!/^[a-z0-9-]+$/.test(name)) {
|
|
5968
5966
|
return {
|
|
5969
5967
|
connector: name,
|
|
@@ -5971,10 +5969,7 @@ function installConnector(name, options = {}) {
|
|
|
5971
5969
|
error: `Invalid connector name '${name}'`
|
|
5972
5970
|
};
|
|
5973
5971
|
}
|
|
5974
|
-
const connectorName = name.startsWith("connect-") ? name : `connect-${name}`;
|
|
5975
5972
|
const sourcePath = getConnectorPath(name);
|
|
5976
|
-
const destDir = join2(targetDir, ".connectors");
|
|
5977
|
-
const destPath = join2(destDir, connectorName);
|
|
5978
5973
|
if (!existsSync2(sourcePath)) {
|
|
5979
5974
|
return {
|
|
5980
5975
|
connector: name,
|
|
@@ -5982,71 +5977,18 @@ function installConnector(name, options = {}) {
|
|
|
5982
5977
|
error: `Connector '${name}' not found`
|
|
5983
5978
|
};
|
|
5984
5979
|
}
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
path: destPath
|
|
5991
|
-
};
|
|
5992
|
-
}
|
|
5993
|
-
try {
|
|
5994
|
-
if (!existsSync2(destDir)) {
|
|
5995
|
-
mkdirSync(destDir, { recursive: true });
|
|
5996
|
-
}
|
|
5997
|
-
cpSync(sourcePath, destPath, { recursive: true });
|
|
5998
|
-
const homeCredDir = join2(homedir(), ".connectors", connectorName);
|
|
5999
|
-
if (existsSync2(homeCredDir)) {
|
|
6000
|
-
const filesToCopy = ["credentials.json", "current_profile"];
|
|
6001
|
-
for (const file of filesToCopy) {
|
|
6002
|
-
const src = join2(homeCredDir, file);
|
|
6003
|
-
if (existsSync2(src)) {
|
|
6004
|
-
cpSync(src, join2(destPath, file));
|
|
6005
|
-
}
|
|
6006
|
-
}
|
|
6007
|
-
const profilesDir = join2(homeCredDir, "profiles");
|
|
6008
|
-
if (existsSync2(profilesDir)) {
|
|
6009
|
-
cpSync(profilesDir, join2(destPath, "profiles"), { recursive: true });
|
|
6010
|
-
}
|
|
6011
|
-
}
|
|
6012
|
-
updateConnectorsIndex(destDir);
|
|
6013
|
-
return {
|
|
6014
|
-
connector: name,
|
|
6015
|
-
success: true,
|
|
6016
|
-
path: destPath
|
|
6017
|
-
};
|
|
6018
|
-
} catch (error) {
|
|
6019
|
-
return {
|
|
6020
|
-
connector: name,
|
|
6021
|
-
success: false,
|
|
6022
|
-
error: error instanceof Error ? error.message : "Unknown error"
|
|
6023
|
-
};
|
|
6024
|
-
}
|
|
6025
|
-
}
|
|
6026
|
-
function updateConnectorsIndex(connectorsDir) {
|
|
6027
|
-
const indexPath = join2(connectorsDir, "index.ts");
|
|
6028
|
-
const connectors = readdirSync(connectorsDir).filter((f) => f.startsWith("connect-") && !f.includes("."));
|
|
6029
|
-
const exports = connectors.map((c) => {
|
|
6030
|
-
const name = c.replace("connect-", "");
|
|
6031
|
-
return `export * as ${name} from './${c}/src/index.js';`;
|
|
6032
|
-
}).join(`
|
|
6033
|
-
`);
|
|
6034
|
-
const content = `/**
|
|
6035
|
-
* Auto-generated index of installed connectors
|
|
6036
|
-
* Do not edit manually - run 'connectors install' to update
|
|
6037
|
-
*/
|
|
6038
|
-
|
|
6039
|
-
${exports}
|
|
6040
|
-
`;
|
|
6041
|
-
writeFileSync(indexPath, content);
|
|
5980
|
+
return {
|
|
5981
|
+
connector: name,
|
|
5982
|
+
success: true,
|
|
5983
|
+
path: sourcePath
|
|
5984
|
+
};
|
|
6042
5985
|
}
|
|
6043
|
-
function getInstalledConnectors(
|
|
6044
|
-
|
|
6045
|
-
if (!existsSync2(connectorsDir)) {
|
|
5986
|
+
function getInstalledConnectors() {
|
|
5987
|
+
if (!existsSync2(CONNECTORS_DIR)) {
|
|
6046
5988
|
return [];
|
|
6047
5989
|
}
|
|
6048
|
-
return readdirSync(
|
|
6049
|
-
const fullPath = join2(
|
|
5990
|
+
return readdirSync(CONNECTORS_DIR).filter((f) => {
|
|
5991
|
+
const fullPath = join2(CONNECTORS_DIR, f);
|
|
6050
5992
|
return f.startsWith("connect-") && statSync(fullPath).isDirectory();
|
|
6051
5993
|
}).map((f) => f.replace("connect-", ""));
|
|
6052
5994
|
}
|
|
@@ -6092,22 +6034,14 @@ function parseEnvVarsTable(section) {
|
|
|
6092
6034
|
}
|
|
6093
6035
|
return vars;
|
|
6094
6036
|
}
|
|
6095
|
-
function removeConnector(name
|
|
6096
|
-
|
|
6097
|
-
const connectorsDir = join2(targetDir, ".connectors");
|
|
6098
|
-
const connectorPath = join2(connectorsDir, connectorName);
|
|
6099
|
-
if (!existsSync2(connectorPath)) {
|
|
6100
|
-
return false;
|
|
6101
|
-
}
|
|
6102
|
-
rmSync(connectorPath, { recursive: true });
|
|
6103
|
-
updateConnectorsIndex(connectorsDir);
|
|
6104
|
-
return true;
|
|
6037
|
+
function removeConnector(name) {
|
|
6038
|
+
return false;
|
|
6105
6039
|
}
|
|
6106
6040
|
|
|
6107
6041
|
// src/server/auth.ts
|
|
6108
|
-
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync
|
|
6042
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync, mkdirSync, readdirSync as readdirSync2, rmSync, statSync as statSync2 } from "fs";
|
|
6109
6043
|
import { randomBytes } from "crypto";
|
|
6110
|
-
import { homedir
|
|
6044
|
+
import { homedir } from "os";
|
|
6111
6045
|
import { join as join3 } from "path";
|
|
6112
6046
|
var FETCH_TIMEOUT = 1e4;
|
|
6113
6047
|
var oauthStateStore = new Map;
|
|
@@ -6164,7 +6098,7 @@ function getAuthType(name) {
|
|
|
6164
6098
|
}
|
|
6165
6099
|
function getConnectorConfigDir(name) {
|
|
6166
6100
|
const connectorName = name.startsWith("connect-") ? name : `connect-${name}`;
|
|
6167
|
-
return join3(
|
|
6101
|
+
return join3(homedir(), ".connectors", connectorName);
|
|
6168
6102
|
}
|
|
6169
6103
|
function getCurrentProfile(name) {
|
|
6170
6104
|
const configDir = getConnectorConfigDir(name);
|
|
@@ -6257,7 +6191,7 @@ function saveApiKey(name, key, field) {
|
|
|
6257
6191
|
const keyField = field || guessKeyField(name);
|
|
6258
6192
|
if (keyField === "clientId" || keyField === "clientSecret") {
|
|
6259
6193
|
const credentialsFile = join3(configDir, "credentials.json");
|
|
6260
|
-
|
|
6194
|
+
mkdirSync(configDir, { recursive: true });
|
|
6261
6195
|
let creds = {};
|
|
6262
6196
|
if (existsSync3(credentialsFile)) {
|
|
6263
6197
|
try {
|
|
@@ -6265,7 +6199,7 @@ function saveApiKey(name, key, field) {
|
|
|
6265
6199
|
} catch {}
|
|
6266
6200
|
}
|
|
6267
6201
|
creds[keyField] = key;
|
|
6268
|
-
|
|
6202
|
+
writeFileSync(credentialsFile, JSON.stringify(creds, null, 2));
|
|
6269
6203
|
return;
|
|
6270
6204
|
}
|
|
6271
6205
|
const profileFile = join3(configDir, "profiles", `${profile}.json`);
|
|
@@ -6276,7 +6210,7 @@ function saveApiKey(name, key, field) {
|
|
|
6276
6210
|
config = JSON.parse(readFileSync3(profileFile, "utf-8"));
|
|
6277
6211
|
} catch {}
|
|
6278
6212
|
config[keyField] = key;
|
|
6279
|
-
|
|
6213
|
+
writeFileSync(profileFile, JSON.stringify(config, null, 2));
|
|
6280
6214
|
return;
|
|
6281
6215
|
}
|
|
6282
6216
|
if (existsSync3(profileDir)) {
|
|
@@ -6288,11 +6222,11 @@ function saveApiKey(name, key, field) {
|
|
|
6288
6222
|
} catch {}
|
|
6289
6223
|
}
|
|
6290
6224
|
config[keyField] = key;
|
|
6291
|
-
|
|
6225
|
+
writeFileSync(configFile, JSON.stringify(config, null, 2));
|
|
6292
6226
|
return;
|
|
6293
6227
|
}
|
|
6294
|
-
|
|
6295
|
-
|
|
6228
|
+
mkdirSync(profileDir, { recursive: true });
|
|
6229
|
+
writeFileSync(join3(profileDir, "config.json"), JSON.stringify({ [keyField]: key }, null, 2));
|
|
6296
6230
|
}
|
|
6297
6231
|
function guessKeyField(name) {
|
|
6298
6232
|
const docs = getConnectorDocs(name);
|
|
@@ -6393,9 +6327,9 @@ function saveOAuthTokens(name, tokens) {
|
|
|
6393
6327
|
const configDir = getConnectorConfigDir(name);
|
|
6394
6328
|
const profile = getCurrentProfile(name);
|
|
6395
6329
|
const profileDir = join3(configDir, "profiles", profile);
|
|
6396
|
-
|
|
6330
|
+
mkdirSync(profileDir, { recursive: true });
|
|
6397
6331
|
const tokensFile = join3(profileDir, "tokens.json");
|
|
6398
|
-
|
|
6332
|
+
writeFileSync(tokensFile, JSON.stringify(tokens, null, 2), { mode: 384 });
|
|
6399
6333
|
}
|
|
6400
6334
|
async function refreshOAuthToken(name) {
|
|
6401
6335
|
const oauthConfig = getOAuthConfig(name);
|
|
@@ -6455,8 +6389,8 @@ function listProfiles(name) {
|
|
|
6455
6389
|
}
|
|
6456
6390
|
function switchProfile(name, profile) {
|
|
6457
6391
|
const configDir = getConnectorConfigDir(name);
|
|
6458
|
-
|
|
6459
|
-
|
|
6392
|
+
mkdirSync(configDir, { recursive: true });
|
|
6393
|
+
writeFileSync(join3(configDir, "current_profile"), profile);
|
|
6460
6394
|
}
|
|
6461
6395
|
function deleteProfile(name, profile) {
|
|
6462
6396
|
if (profile === "default")
|
|
@@ -6465,7 +6399,7 @@ function deleteProfile(name, profile) {
|
|
|
6465
6399
|
const profilesDir = join3(configDir, "profiles");
|
|
6466
6400
|
const profileFile = join3(profilesDir, `${profile}.json`);
|
|
6467
6401
|
if (existsSync3(profileFile)) {
|
|
6468
|
-
|
|
6402
|
+
rmSync(profileFile);
|
|
6469
6403
|
if (getCurrentProfile(name) === profile) {
|
|
6470
6404
|
switchProfile(name, "default");
|
|
6471
6405
|
}
|
|
@@ -6473,7 +6407,7 @@ function deleteProfile(name, profile) {
|
|
|
6473
6407
|
}
|
|
6474
6408
|
const profileDir = join3(profilesDir, profile);
|
|
6475
6409
|
if (existsSync3(profileDir)) {
|
|
6476
|
-
|
|
6410
|
+
rmSync(profileDir, { recursive: true });
|
|
6477
6411
|
if (getCurrentProfile(name) === profile) {
|
|
6478
6412
|
switchProfile(name, "default");
|
|
6479
6413
|
}
|
|
@@ -6742,10 +6676,7 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
6742
6676
|
if (!isValidConnectorName(name))
|
|
6743
6677
|
return json({ error: "Invalid connector name" }, 400, port);
|
|
6744
6678
|
try {
|
|
6745
|
-
|
|
6746
|
-
if (!removed) {
|
|
6747
|
-
return json({ error: `Connector '${name}' is not installed` }, 404, port);
|
|
6748
|
-
}
|
|
6679
|
+
removeConnector(name);
|
|
6749
6680
|
logActivity("uninstalled", name);
|
|
6750
6681
|
return json({ success: true, name }, 200, port);
|
|
6751
6682
|
} catch (e) {
|
|
@@ -6778,7 +6709,7 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
6778
6709
|
return json({ error: "Invalid connector name" }, 400, port);
|
|
6779
6710
|
try {
|
|
6780
6711
|
const profiles = listProfiles(name);
|
|
6781
|
-
const configDir = join4(
|
|
6712
|
+
const configDir = join4(homedir2(), ".connectors", name.startsWith("connect-") ? name : `connect-${name}`);
|
|
6782
6713
|
const currentProfileFile = join4(configDir, "current_profile");
|
|
6783
6714
|
let current = "default";
|
|
6784
6715
|
if (existsSync4(currentProfileFile)) {
|
|
@@ -6830,7 +6761,7 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
6830
6761
|
}
|
|
6831
6762
|
if (path === "/api/export" && method === "GET") {
|
|
6832
6763
|
try {
|
|
6833
|
-
const connectDir = join4(
|
|
6764
|
+
const connectDir = join4(homedir2(), ".connectors");
|
|
6834
6765
|
const result = {};
|
|
6835
6766
|
if (existsSync4(connectDir)) {
|
|
6836
6767
|
const entries = readdirSync3(connectDir, { withFileTypes: true });
|
|
@@ -6890,7 +6821,7 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
6890
6821
|
return json({ error: "Invalid import format: missing 'connectors' object" }, 400, port);
|
|
6891
6822
|
}
|
|
6892
6823
|
let imported = 0;
|
|
6893
|
-
const connectDir = join4(
|
|
6824
|
+
const connectDir = join4(homedir2(), ".connectors");
|
|
6894
6825
|
for (const [connectorName, data] of Object.entries(body.connectors)) {
|
|
6895
6826
|
if (!isValidConnectorName(connectorName))
|
|
6896
6827
|
continue;
|
|
@@ -6901,9 +6832,9 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
6901
6832
|
for (const [profileName, config] of Object.entries(data.profiles)) {
|
|
6902
6833
|
if (!config || typeof config !== "object")
|
|
6903
6834
|
continue;
|
|
6904
|
-
|
|
6835
|
+
mkdirSync2(profilesDir, { recursive: true });
|
|
6905
6836
|
const profileFile = join4(profilesDir, `${profileName}.json`);
|
|
6906
|
-
|
|
6837
|
+
writeFileSync2(profileFile, JSON.stringify(config, null, 2));
|
|
6907
6838
|
imported++;
|
|
6908
6839
|
}
|
|
6909
6840
|
}
|
package/dist/index.js
CHANGED
|
@@ -5961,8 +5961,7 @@ function loadConnectorVersions() {
|
|
|
5961
5961
|
}
|
|
5962
5962
|
}
|
|
5963
5963
|
// src/lib/installer.ts
|
|
5964
|
-
import { existsSync as existsSync2,
|
|
5965
|
-
import { homedir } from "os";
|
|
5964
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync, statSync } from "fs";
|
|
5966
5965
|
import { join as join2, dirname as dirname2 } from "path";
|
|
5967
5966
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5968
5967
|
var __dirname2 = dirname2(fileURLToPath2(import.meta.url));
|
|
@@ -5984,7 +5983,6 @@ function connectorExists(name) {
|
|
|
5984
5983
|
return existsSync2(getConnectorPath(name));
|
|
5985
5984
|
}
|
|
5986
5985
|
function installConnector(name, options = {}) {
|
|
5987
|
-
const { targetDir = process.cwd(), overwrite = false } = options;
|
|
5988
5986
|
if (!/^[a-z0-9-]+$/.test(name)) {
|
|
5989
5987
|
return {
|
|
5990
5988
|
connector: name,
|
|
@@ -5992,10 +5990,7 @@ function installConnector(name, options = {}) {
|
|
|
5992
5990
|
error: `Invalid connector name '${name}'`
|
|
5993
5991
|
};
|
|
5994
5992
|
}
|
|
5995
|
-
const connectorName = name.startsWith("connect-") ? name : `connect-${name}`;
|
|
5996
5993
|
const sourcePath = getConnectorPath(name);
|
|
5997
|
-
const destDir = join2(targetDir, ".connectors");
|
|
5998
|
-
const destPath = join2(destDir, connectorName);
|
|
5999
5994
|
if (!existsSync2(sourcePath)) {
|
|
6000
5995
|
return {
|
|
6001
5996
|
connector: name,
|
|
@@ -6003,74 +5998,21 @@ function installConnector(name, options = {}) {
|
|
|
6003
5998
|
error: `Connector '${name}' not found`
|
|
6004
5999
|
};
|
|
6005
6000
|
}
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
path: destPath
|
|
6012
|
-
};
|
|
6013
|
-
}
|
|
6014
|
-
try {
|
|
6015
|
-
if (!existsSync2(destDir)) {
|
|
6016
|
-
mkdirSync(destDir, { recursive: true });
|
|
6017
|
-
}
|
|
6018
|
-
cpSync(sourcePath, destPath, { recursive: true });
|
|
6019
|
-
const homeCredDir = join2(homedir(), ".connectors", connectorName);
|
|
6020
|
-
if (existsSync2(homeCredDir)) {
|
|
6021
|
-
const filesToCopy = ["credentials.json", "current_profile"];
|
|
6022
|
-
for (const file of filesToCopy) {
|
|
6023
|
-
const src = join2(homeCredDir, file);
|
|
6024
|
-
if (existsSync2(src)) {
|
|
6025
|
-
cpSync(src, join2(destPath, file));
|
|
6026
|
-
}
|
|
6027
|
-
}
|
|
6028
|
-
const profilesDir = join2(homeCredDir, "profiles");
|
|
6029
|
-
if (existsSync2(profilesDir)) {
|
|
6030
|
-
cpSync(profilesDir, join2(destPath, "profiles"), { recursive: true });
|
|
6031
|
-
}
|
|
6032
|
-
}
|
|
6033
|
-
updateConnectorsIndex(destDir);
|
|
6034
|
-
return {
|
|
6035
|
-
connector: name,
|
|
6036
|
-
success: true,
|
|
6037
|
-
path: destPath
|
|
6038
|
-
};
|
|
6039
|
-
} catch (error) {
|
|
6040
|
-
return {
|
|
6041
|
-
connector: name,
|
|
6042
|
-
success: false,
|
|
6043
|
-
error: error instanceof Error ? error.message : "Unknown error"
|
|
6044
|
-
};
|
|
6045
|
-
}
|
|
6001
|
+
return {
|
|
6002
|
+
connector: name,
|
|
6003
|
+
success: true,
|
|
6004
|
+
path: sourcePath
|
|
6005
|
+
};
|
|
6046
6006
|
}
|
|
6047
6007
|
function installConnectors(names, options = {}) {
|
|
6048
6008
|
return names.map((name) => installConnector(name, options));
|
|
6049
6009
|
}
|
|
6050
|
-
function
|
|
6051
|
-
|
|
6052
|
-
const connectors = readdirSync(connectorsDir).filter((f) => f.startsWith("connect-") && !f.includes("."));
|
|
6053
|
-
const exports = connectors.map((c) => {
|
|
6054
|
-
const name = c.replace("connect-", "");
|
|
6055
|
-
return `export * as ${name} from './${c}/src/index.js';`;
|
|
6056
|
-
}).join(`
|
|
6057
|
-
`);
|
|
6058
|
-
const content = `/**
|
|
6059
|
-
* Auto-generated index of installed connectors
|
|
6060
|
-
* Do not edit manually - run 'connectors install' to update
|
|
6061
|
-
*/
|
|
6062
|
-
|
|
6063
|
-
${exports}
|
|
6064
|
-
`;
|
|
6065
|
-
writeFileSync(indexPath, content);
|
|
6066
|
-
}
|
|
6067
|
-
function getInstalledConnectors(targetDir = process.cwd()) {
|
|
6068
|
-
const connectorsDir = join2(targetDir, ".connectors");
|
|
6069
|
-
if (!existsSync2(connectorsDir)) {
|
|
6010
|
+
function getInstalledConnectors() {
|
|
6011
|
+
if (!existsSync2(CONNECTORS_DIR)) {
|
|
6070
6012
|
return [];
|
|
6071
6013
|
}
|
|
6072
|
-
return readdirSync(
|
|
6073
|
-
const fullPath = join2(
|
|
6014
|
+
return readdirSync(CONNECTORS_DIR).filter((f) => {
|
|
6015
|
+
const fullPath = join2(CONNECTORS_DIR, f);
|
|
6074
6016
|
return f.startsWith("connect-") && statSync(fullPath).isDirectory();
|
|
6075
6017
|
}).map((f) => f.replace("connect-", ""));
|
|
6076
6018
|
}
|
|
@@ -6116,16 +6058,8 @@ function parseEnvVarsTable(section) {
|
|
|
6116
6058
|
}
|
|
6117
6059
|
return vars;
|
|
6118
6060
|
}
|
|
6119
|
-
function removeConnector(name
|
|
6120
|
-
|
|
6121
|
-
const connectorsDir = join2(targetDir, ".connectors");
|
|
6122
|
-
const connectorPath = join2(connectorsDir, connectorName);
|
|
6123
|
-
if (!existsSync2(connectorPath)) {
|
|
6124
|
-
return false;
|
|
6125
|
-
}
|
|
6126
|
-
rmSync(connectorPath, { recursive: true });
|
|
6127
|
-
updateConnectorsIndex(connectorsDir);
|
|
6128
|
-
return true;
|
|
6061
|
+
function removeConnector(name) {
|
|
6062
|
+
return false;
|
|
6129
6063
|
}
|
|
6130
6064
|
// src/lib/runner.ts
|
|
6131
6065
|
import { existsSync as existsSync3 } from "fs";
|
package/dist/lib/installer.d.ts
CHANGED
|
@@ -8,7 +8,6 @@ export interface InstallResult {
|
|
|
8
8
|
path?: string;
|
|
9
9
|
}
|
|
10
10
|
export interface InstallOptions {
|
|
11
|
-
targetDir?: string;
|
|
12
11
|
overwrite?: boolean;
|
|
13
12
|
}
|
|
14
13
|
/**
|
|
@@ -20,7 +19,8 @@ export declare function getConnectorPath(name: string): string;
|
|
|
20
19
|
*/
|
|
21
20
|
export declare function connectorExists(name: string): boolean;
|
|
22
21
|
/**
|
|
23
|
-
* Install a single connector
|
|
22
|
+
* Install a single connector — verifies it exists in the global package.
|
|
23
|
+
* Auth/tokens always live in ~/.connectors/connect-{name}/ and are never touched here.
|
|
24
24
|
*/
|
|
25
25
|
export declare function installConnector(name: string, options?: InstallOptions): InstallResult;
|
|
26
26
|
/**
|
|
@@ -28,9 +28,9 @@ export declare function installConnector(name: string, options?: InstallOptions)
|
|
|
28
28
|
*/
|
|
29
29
|
export declare function installConnectors(names: string[], options?: InstallOptions): InstallResult[];
|
|
30
30
|
/**
|
|
31
|
-
* Get list of
|
|
31
|
+
* Get list of available connectors from the global package
|
|
32
32
|
*/
|
|
33
|
-
export declare function getInstalledConnectors(
|
|
33
|
+
export declare function getInstalledConnectors(): string[];
|
|
34
34
|
/**
|
|
35
35
|
* Parsed documentation from a connector's CLAUDE.md
|
|
36
36
|
*/
|
|
@@ -50,6 +50,7 @@ export interface ConnectorDocs {
|
|
|
50
50
|
*/
|
|
51
51
|
export declare function getConnectorDocs(name: string): ConnectorDocs | null;
|
|
52
52
|
/**
|
|
53
|
-
* Remove
|
|
53
|
+
* Remove a connector — connectors are part of the global package and cannot be
|
|
54
|
+
* individually removed. This always returns false.
|
|
54
55
|
*/
|
|
55
|
-
export declare function removeConnector(name: string
|
|
56
|
+
export declare function removeConnector(name: string): boolean;
|