heyreach-cli 0.1.1 → 0.1.2

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/dist/index.js CHANGED
@@ -64,7 +64,7 @@ var init_config = __esm({
64
64
  // src/core/errors.ts
65
65
  function classifyHttpError(status, body) {
66
66
  const parsed = safeParse(body);
67
- const message = parsed?.message ?? parsed?.error ?? body;
67
+ const message = parsed?.message || parsed?.error || body || `HTTP ${status} error`;
68
68
  if (status === 401 || status === 403) return new AuthError(message);
69
69
  if (status === 404) return new NotFoundError(message);
70
70
  if (status === 422) return new ValidationError(message);
@@ -255,7 +255,9 @@ function createClient(auth) {
255
255
  return { request, paginate };
256
256
  }
257
257
  function buildUrl(baseUrl, path2, query) {
258
- const url = new URL(path2, baseUrl.endsWith("/") ? baseUrl : baseUrl + "/");
258
+ const base = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
259
+ const cleanPath = path2.startsWith("/") ? path2.slice(1) : path2;
260
+ const url = new URL(cleanPath, base);
259
261
  if (query) {
260
262
  for (const [key, value] of Object.entries(query)) {
261
263
  if (value !== void 0 && value !== null) {
@@ -631,6 +633,7 @@ var init_get_for_lead = __esm({
631
633
  "use strict";
632
634
  init_esm_shims();
633
635
  init_handler();
636
+ init_errors();
634
637
  campaignsGetForLeadCommand = {
635
638
  name: "campaigns_get_for_lead",
636
639
  group: "campaigns",
@@ -658,7 +661,12 @@ var init_get_for_lead = __esm({
658
661
  },
659
662
  endpoint: { method: "POST", path: "/campaign/GetCampaignsForLead" },
660
663
  fieldMappings: { offset: "body", limit: "body", email: "body", linkedinId: "body", profileUrl: "body" },
661
- handler: (input, client) => executeCommand(campaignsGetForLeadCommand, input, client)
664
+ handler: (input, client) => {
665
+ if (!input.email && !input.linkedinId && !input.profileUrl) {
666
+ throw new ValidationError("At least one of --email, --linkedin-id, or --profile-url is required.");
667
+ }
668
+ return executeCommand(campaignsGetForLeadCommand, input, client);
669
+ }
662
670
  };
663
671
  }
664
672
  });
@@ -1257,6 +1265,7 @@ var init_get_for_lead2 = __esm({
1257
1265
  "use strict";
1258
1266
  init_esm_shims();
1259
1267
  init_handler();
1268
+ init_errors();
1260
1269
  listsGetForLeadCommand = {
1261
1270
  name: "lists_get_for_lead",
1262
1271
  group: "lists",
@@ -1281,7 +1290,12 @@ var init_get_for_lead2 = __esm({
1281
1290
  },
1282
1291
  endpoint: { method: "POST", path: "/list/GetListsForLead" },
1283
1292
  fieldMappings: { offset: "body", limit: "body", email: "body", linkedinId: "body", profileUrl: "body" },
1284
- handler: (input, client) => executeCommand(listsGetForLeadCommand, input, client)
1293
+ handler: (input, client) => {
1294
+ if (!input.email && !input.linkedinId && !input.profileUrl) {
1295
+ throw new ValidationError("At least one of --email, --linkedin-id, or --profile-url is required.");
1296
+ }
1297
+ return executeCommand(listsGetForLeadCommand, input, client);
1298
+ }
1285
1299
  };
1286
1300
  }
1287
1301
  });
@@ -1332,8 +1346,8 @@ var init_overview = __esm({
1332
1346
  'heyreach stats overview --start-date 2025-01-01 --end-date 2025-01-31 --campaign-ids "1,2,3"'
1333
1347
  ],
1334
1348
  inputSchema: z24.object({
1335
- startDate: z24.string().describe("Start date (ISO 8601)"),
1336
- endDate: z24.string().describe("End date (ISO 8601)"),
1349
+ startDate: z24.string().optional().describe("Start date (ISO 8601). Defaults to 30 days ago."),
1350
+ endDate: z24.string().optional().describe("End date (ISO 8601). Defaults to today."),
1337
1351
  accountIds: z24.string().optional().describe("Comma-separated LinkedIn account IDs (empty = all)"),
1338
1352
  campaignIds: z24.string().optional().describe("Comma-separated campaign IDs (empty = all)")
1339
1353
  }),
@@ -1348,12 +1362,14 @@ var init_overview = __esm({
1348
1362
  endpoint: { method: "POST", path: "/stats/GetOverallStats" },
1349
1363
  fieldMappings: {},
1350
1364
  handler: async (input, client) => {
1365
+ const now = /* @__PURE__ */ new Date();
1366
+ const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1e3);
1351
1367
  const body = {
1352
- startDate: input.startDate,
1353
- endDate: input.endDate
1368
+ startDate: input.startDate ?? thirtyDaysAgo.toISOString(),
1369
+ endDate: input.endDate ?? now.toISOString(),
1370
+ accountIds: input.accountIds ? input.accountIds.split(",").map((s) => Number(s.trim())) : [],
1371
+ campaignIds: input.campaignIds ? input.campaignIds.split(",").map((s) => Number(s.trim())) : []
1354
1372
  };
1355
- if (input.accountIds) body.accountIds = input.accountIds.split(",").map((s) => Number(s.trim()));
1356
- if (input.campaignIds) body.campaignIds = input.campaignIds.split(",").map((s) => Number(s.trim()));
1357
1373
  return client.request({ method: "POST", path: "/stats/GetOverallStats", body });
1358
1374
  }
1359
1375
  };
@@ -2404,7 +2420,7 @@ function getGlobalOpts(program2) {
2404
2420
  };
2405
2421
  }
2406
2422
  function registerLoginCommand(program2) {
2407
- program2.command("login").description("Save your API key to ~/.heyreach/config.json").option("--org", "Store Organization API key instead of workspace key").action(async (opts) => {
2423
+ program2.command("login").description("Save your API key to ~/.heyreach/config.json").option("--org", "Store Organization API key instead of workspace key").addHelpText("after", "\nExamples:\n $ heyreach login --api-key <key>\n $ heyreach login --org --org-key <key>\n $ heyreach login # interactive prompt").action(async (opts) => {
2408
2424
  const globalOpts = getGlobalOpts(program2);
2409
2425
  const isOrg = opts.org;
2410
2426
  let apiKey = isOrg ? globalOpts.orgKey ?? process.env.HEYREACH_ORG_API_KEY : globalOpts.apiKey ?? process.env.HEYREACH_API_KEY;
@@ -2418,9 +2434,17 @@ function registerLoginCommand(program2) {
2418
2434
  outputError({ error: "API key is required.", code: "VALIDATION_ERROR" }, globalOpts);
2419
2435
  return;
2420
2436
  }
2437
+ try {
2438
+ const checkPath = isOrg ? "/organization/GetWorkspaces" : "/auth/CheckApiKey";
2439
+ const client = createClient({ apiKey, baseUrl: "https://api.heyreach.io/api/public" });
2440
+ await client.request({ method: "GET", path: checkPath });
2441
+ } catch {
2442
+ outputError({ error: `Invalid ${isOrg ? "Organization" : ""} API key. Check your key and try again.`, code: "AUTH_ERROR" }, globalOpts);
2443
+ return;
2444
+ }
2421
2445
  const config = isOrg ? { org_api_key: apiKey } : { api_key: apiKey };
2422
2446
  saveConfig(config);
2423
- output({ success: true, message: "Credentials saved.", config_path: getConfigPath() }, globalOpts);
2447
+ output({ success: true, message: "Credentials saved and verified.", config_path: getConfigPath() }, globalOpts);
2424
2448
  });
2425
2449
  }
2426
2450
  function registerLogoutCommand(program2) {
@@ -2444,9 +2468,11 @@ function registerStatusCommand(program2) {
2444
2468
  }, globalOpts);
2445
2469
  } catch (err) {
2446
2470
  const config = loadConfig();
2471
+ const usedKey = globalOpts.apiKey ?? process.env.HEYREACH_API_KEY ?? config.api_key;
2447
2472
  output({
2448
2473
  authenticated: false,
2449
- api_key: config.api_key ? "***" + config.api_key.slice(-4) : "(not set)",
2474
+ api_key: usedKey ? "***" + usedKey.slice(-4) : "(not set)",
2475
+ api_key_source: globalOpts.apiKey ? "--api-key flag" : process.env.HEYREACH_API_KEY ? "HEYREACH_API_KEY env" : config.api_key ? "config file" : "none",
2450
2476
  config_path: getConfigPath(),
2451
2477
  error: err instanceof Error ? err.message : String(err)
2452
2478
  }, globalOpts);
@@ -2606,7 +2632,7 @@ import { Command } from "commander";
2606
2632
  var program = new Command();
2607
2633
  program.name("heyreach").description(
2608
2634
  "HeyReach CLI \u2014 manage LinkedIn campaigns, leads, lists, inbox, webhooks, and more from your terminal."
2609
- ).version("0.1.0").option("--pretty", "Pretty-print JSON output").option("--quiet", "Suppress output, exit codes only").option("--fields <fields>", "Comma-separated fields to include in output").option("--api-key <key>", "HeyReach workspace API key").option("--org-key <key>", "HeyReach Organization API key");
2635
+ ).version("0.1.2").option("--pretty", "Pretty-print JSON output").option("--quiet", "Suppress output, exit codes only").option("--fields <fields>", "Comma-separated fields to include in output").option("--api-key <key>", "HeyReach workspace API key").option("--org-key <key>", "HeyReach Organization API key");
2610
2636
  registerAllCommands(program);
2611
2637
  program.parse();
2612
2638
  //# sourceMappingURL=index.js.map