salesprompter-cli 0.1.18 → 0.1.20

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.
@@ -1,5 +1,5 @@
1
1
  import { load } from "cheerio";
2
- const LINKEDIN_BASE_URL = "https://www.linkedin.com";
2
+ const DEFAULT_LINKEDIN_BASE_URL = "https://www.linkedin.com";
3
3
  const DEFAULT_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36";
4
4
  function normalizeWhitespace(value) {
5
5
  return (value ?? "").replace(/\s+/g, " ").trim();
@@ -12,6 +12,27 @@ function normalizeDomainInput(value) {
12
12
  .replace(/^www\./, "")
13
13
  .split("/")[0] ?? "";
14
14
  }
15
+ function getLinkedInBaseUrl(env = process.env) {
16
+ const override = env.SALESPROMPTER_LINKEDIN_BASE_URL?.trim();
17
+ if (!override) {
18
+ return DEFAULT_LINKEDIN_BASE_URL;
19
+ }
20
+ return override.replace(/\/+$/, "");
21
+ }
22
+ function isAllowedLinkedInHostname(hostname, env = process.env) {
23
+ if (/(^|\.)linkedin\.com$/i.test(hostname)) {
24
+ return true;
25
+ }
26
+ try {
27
+ return hostname.toLowerCase() === new URL(getLinkedInBaseUrl(env)).hostname.toLowerCase();
28
+ }
29
+ catch {
30
+ return false;
31
+ }
32
+ }
33
+ function buildLinkedInUrl(pathname, env = process.env) {
34
+ return new URL(pathname, `${getLinkedInBaseUrl(env)}/`).toString();
35
+ }
15
36
  function toAbsoluteLinkedInUrl(value) {
16
37
  const trimmed = normalizeWhitespace(value);
17
38
  if (trimmed.length === 0) {
@@ -19,8 +40,8 @@ function toAbsoluteLinkedInUrl(value) {
19
40
  }
20
41
  const url = trimmed.startsWith("http://") || trimmed.startsWith("https://")
21
42
  ? new URL(trimmed)
22
- : new URL(trimmed, LINKEDIN_BASE_URL);
23
- if (!/(^|\.)linkedin\.com$/i.test(url.hostname)) {
43
+ : new URL(trimmed, `${getLinkedInBaseUrl()}/`);
44
+ if (!isAllowedLinkedInHostname(url.hostname)) {
24
45
  return undefined;
25
46
  }
26
47
  url.search = "";
@@ -33,7 +54,7 @@ function toAbsoluteUrl(value) {
33
54
  return undefined;
34
55
  }
35
56
  try {
36
- return new URL(trimmed, LINKEDIN_BASE_URL).toString();
57
+ return new URL(trimmed, `${getLinkedInBaseUrl()}/`).toString();
37
58
  }
38
59
  catch {
39
60
  return undefined;
@@ -424,7 +445,7 @@ function classifyLinkedInInput(input) {
424
445
  return {
425
446
  kind: "search-query",
426
447
  input: trimmed,
427
- url: `${LINKEDIN_BASE_URL}/products/search/?q=${encodeURIComponent(query)}`,
448
+ url: buildLinkedInUrl(`/products/search/?q=${encodeURIComponent(query)}`),
428
449
  query
429
450
  };
430
451
  }
@@ -435,7 +456,7 @@ function classifyLinkedInInput(input) {
435
456
  return {
436
457
  kind: "search-query",
437
458
  input: trimmed,
438
- url: `${LINKEDIN_BASE_URL}/products/search/?q=${encodeURIComponent(query)}`,
459
+ url: buildLinkedInUrl(`/products/search/?q=${encodeURIComponent(query)}`),
439
460
  query
440
461
  };
441
462
  }
@@ -516,7 +537,7 @@ export function createLinkedInHtmlFetcher(fetchImpl = fetch) {
516
537
  };
517
538
  }
518
539
  async function findCategoryByCode(categoryCode, fetchHtml) {
519
- const browseHtml = await fetchHtml(`${LINKEDIN_BASE_URL}/products/categories/browse`);
540
+ const browseHtml = await fetchHtml(buildLinkedInUrl("/products/categories/browse"));
520
541
  const $ = load(browseHtml);
521
542
  const urls = new Set();
522
543
  $('a[href*="/products/categories/"]').each((_, element) => {
@@ -581,7 +602,7 @@ export async function resolveLinkedInProductSource(input, fetchHtml) {
581
602
  }
582
603
  const searchQuery = resolvedInput.query ?? "";
583
604
  const searchUrl = resolvedInput.kind === "domain"
584
- ? `${LINKEDIN_BASE_URL}/products/search/?q=${encodeURIComponent(searchQuery)}`
605
+ ? buildLinkedInUrl(`/products/search/?q=${encodeURIComponent(searchQuery)}`)
585
606
  : resolvedInput.url;
586
607
  const html = await fetchHtml(searchUrl);
587
608
  const search = parseLinkedInProductSearchPage(html, searchUrl);