@hasna/connectors 0.5.9 → 0.6.1
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 +71 -133
- package/bin/mcp.js +1 -1
- package/bin/serve.js +19 -5
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -5448,11 +5448,25 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
5448
5448
|
const redirectUri = `http://localhost:${port}/oauth/${name}/callback`;
|
|
5449
5449
|
await exchangeOAuthCode(name, code, redirectUri);
|
|
5450
5450
|
logActivity("oauth_connected", name);
|
|
5451
|
-
return htmlResponse(`<!DOCTYPE html><html><head><meta charset="utf-8"
|
|
5452
|
-
<
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5451
|
+
return htmlResponse(`<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
5452
|
+
<style>
|
|
5453
|
+
* { margin:0; padding:0; box-sizing:border-box; }
|
|
5454
|
+
body { font-family:ui-sans-serif,system-ui,-apple-system,sans-serif; display:flex; justify-content:center; align-items:center; min-height:100vh; background:#09090b; color:#fafafa; }
|
|
5455
|
+
.card { background:#18181b; border:1px solid #27272a; border-radius:12px; padding:48px 40px; max-width:420px; text-align:center; }
|
|
5456
|
+
.icon { width:64px; height:64px; border-radius:50%; background:#052e16; display:flex; align-items:center; justify-content:center; margin:0 auto 24px; }
|
|
5457
|
+
.icon svg { width:32px; height:32px; color:#22c55e; }
|
|
5458
|
+
h2 { font-size:24px; font-weight:600; margin-bottom:8px; color:#fafafa; }
|
|
5459
|
+
.connector { color:#22c55e; font-weight:600; }
|
|
5460
|
+
.subtitle { color:#a1a1aa; font-size:15px; margin-top:12px; line-height:1.5; }
|
|
5461
|
+
.hint { color:#52525b; font-size:13px; margin-top:24px; }
|
|
5462
|
+
.cmd { background:#27272a; color:#e4e4e7; padding:2px 8px; border-radius:4px; font-family:ui-monospace,monospace; font-size:12px; }
|
|
5463
|
+
</style>
|
|
5464
|
+
</head><body>
|
|
5465
|
+
<div class="card">
|
|
5466
|
+
<div class="icon"><svg fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/></svg></div>
|
|
5467
|
+
<h2>Connected!</h2>
|
|
5468
|
+
<p class="subtitle"><span class="connector">${name}</span> is now authenticated and ready to use.</p>
|
|
5469
|
+
<p class="hint">You can close this window.<br>Try <span class="cmd">connectors run ${name} --help</span></p>
|
|
5456
5470
|
<script>
|
|
5457
5471
|
if (window.opener) {
|
|
5458
5472
|
window.opener.postMessage({ type: 'oauth-complete', connector: '${name}' }, 'http://localhost:${port}');
|
|
@@ -7370,7 +7384,7 @@ var PRESETS = {
|
|
|
7370
7384
|
commerce: { description: "Commerce and finance", connectors: ["stripe", "shopify", "revolut", "mercury", "pandadoc"] }
|
|
7371
7385
|
};
|
|
7372
7386
|
var program2 = new Command;
|
|
7373
|
-
program2.name("connectors").description("Install API connectors for your project").version("0.
|
|
7387
|
+
program2.name("connectors").description("Install API connectors for your project").version("0.6.1").enablePositionalOptions();
|
|
7374
7388
|
program2.command("interactive", { isDefault: true }).alias("i").description("Interactive connector browser").action(() => {
|
|
7375
7389
|
if (!isTTY) {
|
|
7376
7390
|
console.log(`Non-interactive environment detected. Use a subcommand:
|
|
@@ -8371,145 +8385,69 @@ Open this URL to authenticate:
|
|
|
8371
8385
|
}
|
|
8372
8386
|
process.exit(0);
|
|
8373
8387
|
});
|
|
8374
|
-
program2.command("init").option("--json", "Output
|
|
8375
|
-
|
|
8376
|
-
|
|
8377
|
-
|
|
8378
|
-
|
|
8379
|
-
|
|
8380
|
-
|
|
8381
|
-
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
|
|
8388
|
+
program2.command("init").option("--json", "Output presets and suggestions as JSON (non-interactive)", false).description("Get started with Connectors \u2014 see suggestions, presets, and next steps").action(async (options) => {
|
|
8389
|
+
const initPresets = [
|
|
8390
|
+
{ key: "ai", emoji: "\uD83E\uDD16", label: "AI & ML", connectors: ["anthropic", "openai", "groq", "mistral", "googlegemini", "elevenlabs"], description: "AI and ML models" },
|
|
8391
|
+
{ key: "communication", emoji: "\uD83D\uDCAC", label: "Communication", connectors: ["gmail", "slack", "discord", "resend", "twilio"], description: "Messaging and communication" },
|
|
8392
|
+
{ key: "devtools", emoji: "\uD83D\uDEE0", label: "Developer Tools", connectors: ["github", "vercel", "sentry", "docker", "cloudflare", "firecrawl"], description: "Developer tooling" },
|
|
8393
|
+
{ key: "commerce", emoji: "\uD83D\uDCB3", label: "Commerce", connectors: ["stripe", "shopify", "paypal", "revolut", "mercury"], description: "Commerce and finance" },
|
|
8394
|
+
{ key: "google", emoji: "\uD83D\uDCC1", label: "Google Workspace", connectors: ["gmail", "googledrive", "googlecalendar", "googledocs", "googlesheets"], description: "Google Workspace suite" }
|
|
8395
|
+
];
|
|
8396
|
+
const connectorsHome = join6(homedir3(), ".connectors");
|
|
8397
|
+
let configuredCount = 0;
|
|
8398
|
+
const configuredNames = [];
|
|
8399
|
+
try {
|
|
8400
|
+
if (existsSync6(connectorsHome)) {
|
|
8401
|
+
const entries = readdirSync4(connectorsHome).filter((e) => e.startsWith("connect-") && statSync3(join6(connectorsHome, e)).isDirectory());
|
|
8402
|
+
for (const entry of entries) {
|
|
8403
|
+
const profilesDir = join6(connectorsHome, entry, "profiles");
|
|
8404
|
+
if (existsSync6(profilesDir)) {
|
|
8405
|
+
configuredCount++;
|
|
8406
|
+
configuredNames.push(entry.replace(/^connect-/, ""));
|
|
8407
|
+
}
|
|
8408
|
+
}
|
|
8409
|
+
}
|
|
8410
|
+
} catch {}
|
|
8411
|
+
const jsonData = {
|
|
8412
|
+
total: CONNECTORS.length,
|
|
8413
|
+
configured: configuredCount,
|
|
8414
|
+
configuredConnectors: configuredNames,
|
|
8415
|
+
presets: initPresets.map((p) => ({
|
|
8416
|
+
key: p.key,
|
|
8417
|
+
label: p.label,
|
|
8418
|
+
description: p.description,
|
|
8419
|
+
connectors: p.connectors
|
|
8420
|
+
}))
|
|
8421
|
+
};
|
|
8422
|
+
if (options.json || !isTTY) {
|
|
8423
|
+
console.log(JSON.stringify(jsonData, null, 2));
|
|
8386
8424
|
process.exit(0);
|
|
8387
8425
|
return;
|
|
8388
8426
|
}
|
|
8389
|
-
if (!isTTY) {
|
|
8390
|
-
console.error("Interactive mode requires a TTY. Use --json for non-interactive output.");
|
|
8391
|
-
process.exit(1);
|
|
8392
|
-
return;
|
|
8393
|
-
}
|
|
8394
|
-
function ask(question) {
|
|
8395
|
-
return new Promise((resolve) => {
|
|
8396
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
8397
|
-
rl.question(question, (answer) => {
|
|
8398
|
-
rl.close();
|
|
8399
|
-
resolve(answer.trim());
|
|
8400
|
-
});
|
|
8401
|
-
});
|
|
8402
|
-
}
|
|
8403
8427
|
console.log();
|
|
8404
|
-
console.log(chalk2.bold(
|
|
8405
|
-
console.log(chalk2.dim(`Let's get you set up with the API connectors you need.
|
|
8406
|
-
`));
|
|
8407
|
-
console.log(chalk2.bold(`Available categories:
|
|
8408
|
-
`));
|
|
8409
|
-
const categoryList = CATEGORIES.map((cat) => ({
|
|
8410
|
-
name: cat,
|
|
8411
|
-
connectors: getConnectorsByCategory(cat)
|
|
8412
|
-
}));
|
|
8413
|
-
for (let i = 0;i < categoryList.length; i++) {
|
|
8414
|
-
const c = categoryList[i];
|
|
8415
|
-
console.log(` ${chalk2.cyan(String(i + 1).padStart(2))}. ${c.name} ${chalk2.dim(`(${c.connectors.length} connectors)`)}`);
|
|
8416
|
-
}
|
|
8428
|
+
console.log(chalk2.bold(`Welcome to Connectors! ${CONNECTORS.length} API connectors ready to use.`));
|
|
8417
8429
|
console.log();
|
|
8418
|
-
|
|
8419
|
-
|
|
8420
|
-
console.log(
|
|
8421
|
-
No categories selected. Exiting.
|
|
8422
|
-
`));
|
|
8423
|
-
process.exit(0);
|
|
8424
|
-
return;
|
|
8430
|
+
if (configuredCount > 0) {
|
|
8431
|
+
console.log(chalk2.green(` You already have ${configuredCount} connector${configuredCount === 1 ? "" : "s"} configured`) + chalk2.dim(` (${configuredNames.slice(0, 5).join(", ")}${configuredNames.length > 5 ? ", ..." : ""})`));
|
|
8432
|
+
console.log();
|
|
8425
8433
|
}
|
|
8426
|
-
|
|
8427
|
-
if (catIndices.length === 0) {
|
|
8428
|
-
console.log(chalk2.red(`
|
|
8429
|
-
No valid categories selected. Exiting.
|
|
8434
|
+
console.log(chalk2.bold(`Quick start bundles:
|
|
8430
8435
|
`));
|
|
8431
|
-
|
|
8432
|
-
|
|
8433
|
-
|
|
8434
|
-
const selectedCategories = catIndices.map((i) => categoryList[i]);
|
|
8435
|
-
const seen = new Set;
|
|
8436
|
-
const connectorPool = [];
|
|
8437
|
-
for (const cat of selectedCategories) {
|
|
8438
|
-
for (const c of cat.connectors) {
|
|
8439
|
-
if (!seen.has(c.name)) {
|
|
8440
|
-
seen.add(c.name);
|
|
8441
|
-
connectorPool.push({
|
|
8442
|
-
name: c.name,
|
|
8443
|
-
displayName: c.displayName,
|
|
8444
|
-
description: c.description,
|
|
8445
|
-
category: cat.name
|
|
8446
|
-
});
|
|
8447
|
-
}
|
|
8448
|
-
}
|
|
8436
|
+
for (const preset of initPresets) {
|
|
8437
|
+
console.log(` ${preset.emoji} ${chalk2.bold(preset.label)} ${chalk2.dim(`(${preset.connectors.length} connectors)`)}`);
|
|
8438
|
+
console.log(` ${chalk2.dim(preset.connectors.slice(0, 5).join(", ") + (preset.connectors.length > 5 ? ", ..." : ""))}`);
|
|
8449
8439
|
}
|
|
8450
8440
|
console.log();
|
|
8451
|
-
console.log(
|
|
8452
|
-
`));
|
|
8453
|
-
const nameWidth = Math.max(12, ...connectorPool.map((c) => c.name.length)) + 2;
|
|
8454
|
-
for (let i = 0;i < connectorPool.length; i++) {
|
|
8455
|
-
const c = connectorPool[i];
|
|
8456
|
-
console.log(` ${chalk2.cyan(String(i + 1).padStart(3))}. ${c.name.padEnd(nameWidth)}${chalk2.dim(c.description)}`);
|
|
8457
|
-
}
|
|
8441
|
+
console.log(`Run ${chalk2.cyan("connectors install --preset ai")} to install a bundle, or ${chalk2.cyan("connectors setup <name> --key <key>")} to set up a specific connector.`);
|
|
8458
8442
|
console.log();
|
|
8459
|
-
|
|
8460
|
-
if (!connAnswer) {
|
|
8461
|
-
console.log(chalk2.dim(`
|
|
8462
|
-
No connectors selected. Exiting.
|
|
8463
|
-
`));
|
|
8464
|
-
process.exit(0);
|
|
8465
|
-
return;
|
|
8466
|
-
}
|
|
8467
|
-
let toInstall;
|
|
8468
|
-
if (connAnswer.toLowerCase() === "all") {
|
|
8469
|
-
toInstall = connectorPool.map((c) => c.name);
|
|
8470
|
-
} else {
|
|
8471
|
-
const connIndices = connAnswer.split(",").map((s) => parseInt(s.trim(), 10) - 1).filter((i) => i >= 0 && i < connectorPool.length);
|
|
8472
|
-
if (connIndices.length === 0) {
|
|
8473
|
-
console.log(chalk2.red(`
|
|
8474
|
-
No valid connectors selected. Exiting.
|
|
8475
|
-
`));
|
|
8476
|
-
process.exit(1);
|
|
8477
|
-
return;
|
|
8478
|
-
}
|
|
8479
|
-
toInstall = connIndices.map((i) => connectorPool[i].name);
|
|
8480
|
-
}
|
|
8481
|
-
console.log(chalk2.bold(`
|
|
8482
|
-
Installing ${toInstall.length} connector(s)...
|
|
8443
|
+
console.log(chalk2.bold(`Next steps:
|
|
8483
8444
|
`));
|
|
8484
|
-
|
|
8485
|
-
|
|
8486
|
-
|
|
8487
|
-
|
|
8488
|
-
console.log(chalk2.green(` \u2713 ${result.connector}`));
|
|
8489
|
-
succeeded.push(result.connector);
|
|
8490
|
-
} else {
|
|
8491
|
-
console.log(chalk2.red(` \u2717 ${result.connector}: ${result.error}`));
|
|
8492
|
-
}
|
|
8493
|
-
}
|
|
8494
|
-
if (succeeded.length > 0) {
|
|
8495
|
-
console.log(chalk2.bold(`
|
|
8496
|
-
Next steps:
|
|
8497
|
-
`));
|
|
8498
|
-
console.log(` ${chalk2.dim("1.")} Import in your code:`);
|
|
8499
|
-
console.log(` ${chalk2.cyan(`import { ${succeeded.slice(0, 3).join(", ")}${succeeded.length > 3 ? ", ..." : ""} } from './.connectors'`)}`);
|
|
8500
|
-
console.log();
|
|
8501
|
-
console.log(` ${chalk2.dim("2.")} Configure authentication:`);
|
|
8502
|
-
console.log(` ${chalk2.cyan("connectors auth <name>")} ${chalk2.dim("\u2014 set API keys interactively")}`);
|
|
8503
|
-
console.log(` ${chalk2.cyan("connectors serve")} ${chalk2.dim("\u2014 open dashboard for OAuth setup")}`);
|
|
8504
|
-
console.log();
|
|
8505
|
-
console.log(` ${chalk2.dim("3.")} Check connector docs:`);
|
|
8506
|
-
console.log(` ${chalk2.cyan(`connectors docs ${succeeded[0]}`)} ${chalk2.dim("\u2014 see auth & env var details")}`);
|
|
8507
|
-
console.log();
|
|
8508
|
-
console.log(` ${chalk2.dim("4.")} Verify everything works:`);
|
|
8509
|
-
console.log(` ${chalk2.cyan("connectors doctor")} ${chalk2.dim("\u2014 health check all connectors")}`);
|
|
8510
|
-
}
|
|
8445
|
+
console.log(` ${chalk2.cyan("connectors list")} ${chalk2.dim(`\u2014 browse all ${CONNECTORS.length} connectors`)}`);
|
|
8446
|
+
console.log(` ${chalk2.cyan("connectors setup <name> --key <key>")} ${chalk2.dim("\u2014 set up a connector")}`);
|
|
8447
|
+
console.log(` ${chalk2.cyan("connectors ops <name>")} ${chalk2.dim("\u2014 see what a connector can do")}`);
|
|
8448
|
+
console.log(` ${chalk2.cyan("connectors serve")} ${chalk2.dim("\u2014 open the auth dashboard")}`);
|
|
8511
8449
|
console.log();
|
|
8512
|
-
process.exit(
|
|
8450
|
+
process.exit(0);
|
|
8513
8451
|
});
|
|
8514
8452
|
var SENSITIVE_FIELDS = new Set([
|
|
8515
8453
|
"clientsecret",
|
package/bin/mcp.js
CHANGED
|
@@ -20852,7 +20852,7 @@ async function getConnectorCommandHelp(name, command) {
|
|
|
20852
20852
|
loadConnectorVersions();
|
|
20853
20853
|
var server = new McpServer({
|
|
20854
20854
|
name: "connectors",
|
|
20855
|
-
version: "0.
|
|
20855
|
+
version: "0.6.1"
|
|
20856
20856
|
});
|
|
20857
20857
|
server.registerTool("search_connectors", {
|
|
20858
20858
|
title: "Search Connectors",
|
package/bin/serve.js
CHANGED
|
@@ -1926,11 +1926,25 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
1926
1926
|
const redirectUri = `http://localhost:${port}/oauth/${name}/callback`;
|
|
1927
1927
|
await exchangeOAuthCode(name, code, redirectUri);
|
|
1928
1928
|
logActivity("oauth_connected", name);
|
|
1929
|
-
return htmlResponse(`<!DOCTYPE html><html><head><meta charset="utf-8"
|
|
1930
|
-
<
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1929
|
+
return htmlResponse(`<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
1930
|
+
<style>
|
|
1931
|
+
* { margin:0; padding:0; box-sizing:border-box; }
|
|
1932
|
+
body { font-family:ui-sans-serif,system-ui,-apple-system,sans-serif; display:flex; justify-content:center; align-items:center; min-height:100vh; background:#09090b; color:#fafafa; }
|
|
1933
|
+
.card { background:#18181b; border:1px solid #27272a; border-radius:12px; padding:48px 40px; max-width:420px; text-align:center; }
|
|
1934
|
+
.icon { width:64px; height:64px; border-radius:50%; background:#052e16; display:flex; align-items:center; justify-content:center; margin:0 auto 24px; }
|
|
1935
|
+
.icon svg { width:32px; height:32px; color:#22c55e; }
|
|
1936
|
+
h2 { font-size:24px; font-weight:600; margin-bottom:8px; color:#fafafa; }
|
|
1937
|
+
.connector { color:#22c55e; font-weight:600; }
|
|
1938
|
+
.subtitle { color:#a1a1aa; font-size:15px; margin-top:12px; line-height:1.5; }
|
|
1939
|
+
.hint { color:#52525b; font-size:13px; margin-top:24px; }
|
|
1940
|
+
.cmd { background:#27272a; color:#e4e4e7; padding:2px 8px; border-radius:4px; font-family:ui-monospace,monospace; font-size:12px; }
|
|
1941
|
+
</style>
|
|
1942
|
+
</head><body>
|
|
1943
|
+
<div class="card">
|
|
1944
|
+
<div class="icon"><svg fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/></svg></div>
|
|
1945
|
+
<h2>Connected!</h2>
|
|
1946
|
+
<p class="subtitle"><span class="connector">${name}</span> is now authenticated and ready to use.</p>
|
|
1947
|
+
<p class="hint">You can close this window.<br>Try <span class="cmd">connectors run ${name} --help</span></p>
|
|
1934
1948
|
<script>
|
|
1935
1949
|
if (window.opener) {
|
|
1936
1950
|
window.opener.postMessage({ type: 'oauth-complete', connector: '${name}' }, 'http://localhost:${port}');
|