@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 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"></head><body style="font-family:system-ui,sans-serif;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:#0a0a0a;color:#e5e5e5;">
5452
- <div style="text-align:center;">
5453
- <h2 style="color:#22c55e;">Connected!</h2>
5454
- <p style="color:#888;"><strong>${name}</strong> is now authenticated.</p>
5455
- <p style="color:#666;font-size:14px;">You can close this window and return to the dashboard.</p>
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.5.9").enablePositionalOptions();
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 categories and connectors as JSON (non-interactive)", false).description("Guided onboarding: pick categories, choose connectors, install them").action(async (options) => {
8375
- if (options.json) {
8376
- const data = CATEGORIES.map((category) => ({
8377
- name: category,
8378
- connectors: getConnectorsByCategory(category).map((c) => ({
8379
- name: c.name,
8380
- displayName: c.displayName,
8381
- description: c.description,
8382
- version: c.version || null
8383
- }))
8384
- }));
8385
- console.log(JSON.stringify(data, null, 2));
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("Welcome to Connectors!"));
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
- const catAnswer = await ask(chalk2.bold("Pick categories") + chalk2.dim(" (comma-separated numbers, e.g. 1,3,5): "));
8419
- if (!catAnswer) {
8420
- console.log(chalk2.dim(`
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
- const catIndices = catAnswer.split(",").map((s) => parseInt(s.trim(), 10) - 1).filter((i) => i >= 0 && i < categoryList.length);
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
- process.exit(1);
8432
- return;
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(chalk2.bold(`Connectors in ${selectedCategories.map((c) => c.name).join(", ")}:
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
- const connAnswer = await ask(chalk2.bold("Install which connectors?") + chalk2.dim(" (comma-separated numbers, or 'all'): "));
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
- const results = toInstall.map((name) => installConnector(name, { overwrite: false }));
8485
- const succeeded = [];
8486
- for (const result of results) {
8487
- if (result.success) {
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(results.every((r) => r.success) ? 0 : 1);
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.5.9"
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"></head><body style="font-family:system-ui,sans-serif;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:#0a0a0a;color:#e5e5e5;">
1930
- <div style="text-align:center;">
1931
- <h2 style="color:#22c55e;">Connected!</h2>
1932
- <p style="color:#888;"><strong>${name}</strong> is now authenticated.</p>
1933
- <p style="color:#666;font-size:14px;">You can close this window and return to the dashboard.</p>
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}');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/connectors",
3
- "version": "0.5.9",
3
+ "version": "0.6.1",
4
4
  "description": "Open source connector library - Install API connectors with a single command",
5
5
  "type": "module",
6
6
  "bin": {