@hasna/connectors 0.5.1 → 0.5.3

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.
Files changed (3) hide show
  1. package/bin/index.js +167 -6
  2. package/bin/mcp.js +1 -1
  3. package/package.json +1 -1
package/bin/index.js CHANGED
@@ -7281,7 +7281,7 @@ var PRESETS = {
7281
7281
  commerce: { description: "Commerce and finance", connectors: ["stripe", "shopify", "revolut", "mercury", "pandadoc"] }
7282
7282
  };
7283
7283
  var program2 = new Command;
7284
- program2.name("connectors").description("Install API connectors for your project").version("0.5.1").enablePositionalOptions();
7284
+ program2.name("connectors").description("Install API connectors for your project").version("0.5.3").enablePositionalOptions();
7285
7285
  program2.command("interactive", { isDefault: true }).alias("i").description("Interactive connector browser").action(() => {
7286
7286
  if (!isTTY) {
7287
7287
  console.log(`Non-interactive environment detected. Use a subcommand:
@@ -8523,6 +8523,117 @@ program2.command("import").argument("<file>", "JSON backup file to import (use -
8523
8523
  console.log(chalk2.green(`\u2713 Imported ${imported} profile(s)`));
8524
8524
  }
8525
8525
  });
8526
+ 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) => {
8527
+ const oldBase = join6(homedir3(), ".connect");
8528
+ const newBase = join6(homedir3(), ".connectors");
8529
+ if (!existsSync6(oldBase)) {
8530
+ if (options.json) {
8531
+ console.log(JSON.stringify({ imported: [], skipped: [], error: null, message: "No ~/.connect/ directory found" }));
8532
+ } else {
8533
+ console.log(chalk2.dim("No ~/.connect/ directory found. Nothing to import."));
8534
+ }
8535
+ return;
8536
+ }
8537
+ const entries = readdirSync4(oldBase).filter((name) => {
8538
+ if (!name.startsWith("connect-"))
8539
+ return false;
8540
+ try {
8541
+ return statSync3(join6(oldBase, name)).isDirectory();
8542
+ } catch {
8543
+ return false;
8544
+ }
8545
+ });
8546
+ if (entries.length === 0) {
8547
+ if (options.json) {
8548
+ console.log(JSON.stringify({ imported: [], skipped: [], message: "No connect-* directories found in ~/.connect/" }));
8549
+ } else {
8550
+ console.log(chalk2.dim("No connect-* directories found in ~/.connect/. Nothing to import."));
8551
+ }
8552
+ return;
8553
+ }
8554
+ const imported = [];
8555
+ const skipped = [];
8556
+ for (const dirName of entries) {
8557
+ const oldDir = join6(oldBase, dirName);
8558
+ const newDir = join6(newBase, dirName);
8559
+ const connectorName = dirName.replace(/^connect-/, "");
8560
+ const allFiles = listFilesRecursive(oldDir);
8561
+ const authFiles = allFiles.filter((f) => {
8562
+ return f === "credentials.json" || f === "config.json" || f === "tokens.json" || f === "current_profile" || f.startsWith("profiles/") || f.startsWith("profiles\\");
8563
+ });
8564
+ if (authFiles.length === 0)
8565
+ continue;
8566
+ const copiedFiles = [];
8567
+ const skippedFiles = [];
8568
+ for (const relFile of authFiles) {
8569
+ const srcPath = join6(oldDir, relFile);
8570
+ const destPath = join6(newDir, relFile);
8571
+ if (existsSync6(destPath) && !options.force) {
8572
+ skippedFiles.push(relFile);
8573
+ continue;
8574
+ }
8575
+ if (!options.dryRun) {
8576
+ const parentDir = join6(destPath, "..");
8577
+ mkdirSync4(parentDir, { recursive: true });
8578
+ const content = readFileSync5(srcPath);
8579
+ writeFileSync4(destPath, content);
8580
+ }
8581
+ copiedFiles.push(relFile);
8582
+ }
8583
+ if (copiedFiles.length > 0) {
8584
+ imported.push({ connector: connectorName, files: copiedFiles });
8585
+ }
8586
+ if (skippedFiles.length > 0) {
8587
+ skipped.push({ connector: connectorName, files: skippedFiles });
8588
+ }
8589
+ }
8590
+ if (options.json) {
8591
+ console.log(JSON.stringify({ dryRun: options.dryRun, force: options.force, imported, skipped }, null, 2));
8592
+ return;
8593
+ }
8594
+ if (options.dryRun) {
8595
+ console.log(chalk2.bold(`
8596
+ Dry run \u2014 no changes will be made
8597
+ `));
8598
+ } else {
8599
+ console.log(chalk2.bold(`
8600
+ Auth Import Results
8601
+ `));
8602
+ }
8603
+ for (const entry of imported) {
8604
+ console.log(` ${chalk2.green("\u2713")} ${chalk2.cyan(entry.connector)}`);
8605
+ for (const f of entry.files) {
8606
+ console.log(chalk2.dim(` ${options.dryRun ? "would copy" : "copied"}: ${f}`));
8607
+ }
8608
+ }
8609
+ for (const entry of skipped) {
8610
+ console.log(` ${chalk2.yellow("\u2298")} ${chalk2.cyan(entry.connector)}`);
8611
+ for (const f of entry.files) {
8612
+ console.log(chalk2.dim(` skipped (exists): ${f}`));
8613
+ }
8614
+ }
8615
+ if (imported.length === 0 && skipped.length === 0) {
8616
+ console.log(chalk2.dim(" No auth files found to import."));
8617
+ }
8618
+ const totalCopied = imported.reduce((sum, e) => sum + e.files.length, 0);
8619
+ const totalSkipped = skipped.reduce((sum, e) => sum + e.files.length, 0);
8620
+ const parts = [];
8621
+ if (totalCopied > 0)
8622
+ parts.push(chalk2.green(`${totalCopied} file${totalCopied !== 1 ? "s" : ""} ${options.dryRun ? "to copy" : "copied"}`));
8623
+ if (totalSkipped > 0)
8624
+ parts.push(chalk2.yellow(`${totalSkipped} skipped`));
8625
+ if (parts.length > 0) {
8626
+ console.log(`
8627
+ ${chalk2.bold("Summary:")} ${parts.join(", ")}`);
8628
+ }
8629
+ if (options.dryRun) {
8630
+ console.log(chalk2.dim(`
8631
+ Run without --dry-run to apply.
8632
+ `));
8633
+ } else {
8634
+ console.log();
8635
+ }
8636
+ });
8526
8637
  program2.command("upgrade").alias("self-update").option("--check", "Only check for updates, don't install", false).option("--json", "Output as JSON", false).description("Check for updates and upgrade to the latest version").action(async (options) => {
8527
8638
  const currentVersion = program2.version();
8528
8639
  try {
@@ -8744,7 +8855,9 @@ program2.command("whoami").option("--json", "Output as JSON", false).description
8744
8855
  let configured = 0;
8745
8856
  let unconfigured = 0;
8746
8857
  const connectorDetails = [];
8858
+ const seen = new Set;
8747
8859
  for (const name of installed) {
8860
+ seen.add(name);
8748
8861
  const auth = getAuthStatus(name);
8749
8862
  if (auth.configured)
8750
8863
  configured++;
@@ -8758,7 +8871,38 @@ program2.command("whoami").option("--json", "Output as JSON", false).description
8758
8871
  profile = readFileSync5(currentProfileFile, "utf-8").trim() || "default";
8759
8872
  } catch {}
8760
8873
  }
8761
- connectorDetails.push({ name, configured: auth.configured, authType: auth.type, profile });
8874
+ connectorDetails.push({ name, configured: auth.configured, authType: auth.type, profile, source: "project" });
8875
+ }
8876
+ if (existsSync6(configDir)) {
8877
+ try {
8878
+ const globalDirs = readdirSync4(configDir).filter((f) => {
8879
+ if (!f.startsWith("connect-"))
8880
+ return false;
8881
+ try {
8882
+ return statSync3(join6(configDir, f)).isDirectory();
8883
+ } catch {
8884
+ return false;
8885
+ }
8886
+ });
8887
+ for (const dir of globalDirs) {
8888
+ const name = dir.replace("connect-", "");
8889
+ if (seen.has(name))
8890
+ continue;
8891
+ const auth = getAuthStatus(name);
8892
+ if (!auth.configured)
8893
+ continue;
8894
+ seen.add(name);
8895
+ configured++;
8896
+ const currentProfileFile = join6(configDir, dir, "current_profile");
8897
+ let profile = "default";
8898
+ if (existsSync6(currentProfileFile)) {
8899
+ try {
8900
+ profile = readFileSync5(currentProfileFile, "utf-8").trim() || "default";
8901
+ } catch {}
8902
+ }
8903
+ connectorDetails.push({ name, configured: true, authType: auth.type, profile, source: "global" });
8904
+ }
8905
+ } catch {}
8762
8906
  }
8763
8907
  if (options.json) {
8764
8908
  console.log(JSON.stringify({
@@ -8779,17 +8923,34 @@ Connectors Setup
8779
8923
  console.log(` Config: ${configDir}${existsSync6(configDir) ? "" : chalk2.dim(" (not created yet)")}`);
8780
8924
  console.log(` Installed: ${installed.length} connector${installed.length !== 1 ? "s" : ""}`);
8781
8925
  console.log(` Configured: ${chalk2.green(String(configured))} ready, ${unconfigured > 0 ? chalk2.red(String(unconfigured)) : chalk2.dim("0")} need auth`);
8782
- if (connectorDetails.length > 0) {
8926
+ const projectConnectors = connectorDetails.filter((c) => c.source === "project");
8927
+ const globalConnectors = connectorDetails.filter((c) => c.source === "global");
8928
+ if (projectConnectors.length > 0) {
8783
8929
  console.log(chalk2.bold(`
8784
- Connectors:
8930
+ Project Connectors:
8785
8931
  `));
8786
- const nameWidth = Math.max(10, ...connectorDetails.map((c) => c.name.length)) + 2;
8787
- for (const c of connectorDetails) {
8932
+ const nameWidth = Math.max(10, ...projectConnectors.map((c) => c.name.length)) + 2;
8933
+ for (const c of projectConnectors) {
8788
8934
  const status = c.configured ? chalk2.green("\u2713") : chalk2.red("\u2717");
8789
8935
  const profileLabel = c.profile !== "default" ? chalk2.dim(` [${c.profile}]`) : "";
8790
8936
  console.log(` ${status} ${chalk2.cyan(c.name.padEnd(nameWidth))}${c.authType.padEnd(8)}${profileLabel}`);
8791
8937
  }
8792
8938
  }
8939
+ if (globalConnectors.length > 0) {
8940
+ console.log(chalk2.bold(`
8941
+ Global Connectors`) + chalk2.dim(" (~/.connectors)") + chalk2.bold(`:
8942
+ `));
8943
+ const nameWidth = Math.max(10, ...globalConnectors.map((c) => c.name.length)) + 2;
8944
+ for (const c of globalConnectors) {
8945
+ const status = c.configured ? chalk2.green("\u2713") : chalk2.red("\u2717");
8946
+ const profileLabel = c.profile !== "default" ? chalk2.dim(` [${c.profile}]`) : "";
8947
+ console.log(` ${status} ${chalk2.cyan(c.name.padEnd(nameWidth))}${c.authType.padEnd(8)}${profileLabel}`);
8948
+ }
8949
+ }
8950
+ if (connectorDetails.length === 0) {
8951
+ console.log(chalk2.dim(`
8952
+ No connectors installed or configured.`));
8953
+ }
8793
8954
  console.log();
8794
8955
  });
8795
8956
  program2.command("test").argument("[connector]", "Connector to test (default: all installed)").option("--json", "Output as JSON", false).option("--timeout <ms>", "Request timeout in milliseconds", "10000").description("Verify API credentials by making a real request to the connector's API").action(async (connector, options) => {
package/bin/mcp.js CHANGED
@@ -20763,7 +20763,7 @@ async function getConnectorCommandHelp(name, command) {
20763
20763
  loadConnectorVersions();
20764
20764
  var server = new McpServer({
20765
20765
  name: "connectors",
20766
- version: "0.5.1"
20766
+ version: "0.5.3"
20767
20767
  });
20768
20768
  server.registerTool("search_connectors", {
20769
20769
  title: "Search Connectors",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/connectors",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "Open source connector library - Install API connectors with a single command",
5
5
  "type": "module",
6
6
  "bin": {