salesprompter-cli 0.1.37 → 0.1.38
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/cli.js +93 -11
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
3
4
|
import { access, appendFile, mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
|
|
4
5
|
import { createRequire } from "node:module";
|
|
5
6
|
import os from "node:os";
|
|
@@ -25,7 +26,8 @@ import { InstantlySyncProvider } from "./instantly.js";
|
|
|
25
26
|
import { backfillLinkedInCompanies } from "./linkedin-companies.js";
|
|
26
27
|
import { parseLinkedInCompanyPage } from "./linkedin-companies.js";
|
|
27
28
|
import { crawlLinkedInProductCategory } from "./linkedin-products.js";
|
|
28
|
-
import { claimValidatedSalesNavigatorSessionCookieForCli, createLinkedInSessionSupabaseClient, resolveConfiguredEnvValue } from "./linkedin-session.js";
|
|
29
|
+
import { claimValidatedSalesNavigatorSessionCookieForCli, createLinkedInSessionSupabaseClient, probeSalesNavigatorSearchSession, resolveConfiguredEnvValue } from "./linkedin-session.js";
|
|
30
|
+
import { extractLiAtCookieValue } from "./linkedin-session-contracts.js";
|
|
29
31
|
import { buildLeadlistsFunnelQueries } from "./leadlists-funnel.js";
|
|
30
32
|
import { readJsonFile, splitCsv, writeJsonFile, writeTextFile } from "./io.js";
|
|
31
33
|
import { buildSalesNavigatorCrawlPreview, createSalesNavigatorCrawlSeed, DEFAULT_SALES_NAVIGATOR_CRAWL_DIMENSIONS, buildSalesNavigatorPeopleSlice, deriveSalesNavigatorTitleQuerySeeds, expandSalesNavigatorCrawlAttempt, SalesNavigatorSliceTooBroadError } from "./sales-navigator.js";
|
|
@@ -5869,6 +5871,15 @@ async function runSalesNavigatorExport(session, payload, traceId, logOptions = {
|
|
|
5869
5871
|
}
|
|
5870
5872
|
}
|
|
5871
5873
|
async function startSalesNavigatorExport(session, payload, traceId) {
|
|
5874
|
+
const exportSession = await resolveSalesNavigatorExportSessionOverride(payload.slicedQueryUrl, {
|
|
5875
|
+
source: "cli_salesnav_export_start"
|
|
5876
|
+
});
|
|
5877
|
+
const sessionOverridePayload = exportSession
|
|
5878
|
+
? {
|
|
5879
|
+
sessionCookie: exportSession.sessionCookie,
|
|
5880
|
+
selectedSessionCookieSha256: exportSession.selectedSessionCookieSha256
|
|
5881
|
+
}
|
|
5882
|
+
: {};
|
|
5872
5883
|
return await fetchCliJson(session, (currentSession) => fetch(`${currentSession.apiBaseUrl}/api/cli/salesnav/export`, {
|
|
5873
5884
|
method: "POST",
|
|
5874
5885
|
signal: AbortSignal.timeout(SALES_NAVIGATOR_EXPORT_START_TIMEOUT_MS),
|
|
@@ -5879,7 +5890,8 @@ async function startSalesNavigatorExport(session, payload, traceId) {
|
|
|
5879
5890
|
},
|
|
5880
5891
|
body: JSON.stringify({
|
|
5881
5892
|
...payload,
|
|
5882
|
-
appliedFilters: serializeSalesNavigatorFiltersForApi(payload.appliedFilters)
|
|
5893
|
+
appliedFilters: serializeSalesNavigatorFiltersForApi(payload.appliedFilters),
|
|
5894
|
+
...sessionOverridePayload
|
|
5883
5895
|
})
|
|
5884
5896
|
}), SalesNavigatorExportStartResponseSchema);
|
|
5885
5897
|
}
|
|
@@ -6686,25 +6698,95 @@ function buildSalesNavigatorSliceFailureReport(slice, error, options) {
|
|
|
6686
6698
|
function formatSalesNavigatorSplitTrail(splitTrail) {
|
|
6687
6699
|
return splitTrail.map((entry) => `${entry.key}:${entry.value.text}`);
|
|
6688
6700
|
}
|
|
6701
|
+
let cachedSalesNavigatorExportSessionOverride = null;
|
|
6702
|
+
function hashSalesNavigatorSessionCookieForPhantombuster(sessionCookie) {
|
|
6703
|
+
const liAt = extractLiAtCookieValue(sessionCookie);
|
|
6704
|
+
if (!liAt) {
|
|
6705
|
+
return null;
|
|
6706
|
+
}
|
|
6707
|
+
return createHash("sha256").update(liAt).digest("hex");
|
|
6708
|
+
}
|
|
6709
|
+
function normalizeSalesNavigatorSessionCookieForPhantombuster(sessionCookie) {
|
|
6710
|
+
return extractLiAtCookieValue(sessionCookie) ?? sessionCookie;
|
|
6711
|
+
}
|
|
6712
|
+
function cacheSalesNavigatorExportSessionOverride(queryUrl, value) {
|
|
6713
|
+
cachedSalesNavigatorExportSessionOverride = {
|
|
6714
|
+
queryUrl,
|
|
6715
|
+
expiresAt: Date.now() + 120_000,
|
|
6716
|
+
value
|
|
6717
|
+
};
|
|
6718
|
+
return value;
|
|
6719
|
+
}
|
|
6720
|
+
async function resolveSalesNavigatorExportSessionOverride(queryUrl, options) {
|
|
6721
|
+
if (cachedSalesNavigatorExportSessionOverride &&
|
|
6722
|
+
cachedSalesNavigatorExportSessionOverride.queryUrl === queryUrl &&
|
|
6723
|
+
cachedSalesNavigatorExportSessionOverride.expiresAt > Date.now()) {
|
|
6724
|
+
return cachedSalesNavigatorExportSessionOverride.value;
|
|
6725
|
+
}
|
|
6726
|
+
const localExtensionConfig = await readLocalLinkedInExtensionDirectLookupConfig();
|
|
6727
|
+
if (localExtensionConfig?.cookie) {
|
|
6728
|
+
const selectedSessionCookieSha256 = hashSalesNavigatorSessionCookieForPhantombuster(localExtensionConfig.cookie);
|
|
6729
|
+
if (process.env.SALESPROMPTER_SALESNAV_EXPORT_SKIP_EXTENSION_PREFLIGHT === "1") {
|
|
6730
|
+
return cacheSalesNavigatorExportSessionOverride(queryUrl, {
|
|
6731
|
+
sessionCookie: normalizeSalesNavigatorSessionCookieForPhantombuster(localExtensionConfig.cookie),
|
|
6732
|
+
selectedSessionCookieSha256,
|
|
6733
|
+
source: "chrome_extension"
|
|
6734
|
+
});
|
|
6735
|
+
}
|
|
6736
|
+
const probe = await probeSalesNavigatorSearchSession(localExtensionConfig.cookie, queryUrl, {
|
|
6737
|
+
timeoutMs: 8000
|
|
6738
|
+
});
|
|
6739
|
+
await options.logger?.log("salesnav.export.session.chrome_extension.preflight", {
|
|
6740
|
+
source: options.source,
|
|
6741
|
+
queryUrl,
|
|
6742
|
+
status: probe.status,
|
|
6743
|
+
selectedSessionCookieSha256,
|
|
6744
|
+
finalUrl: probe.finalUrl,
|
|
6745
|
+
validationError: probe.validationError
|
|
6746
|
+
});
|
|
6747
|
+
if (probe.status === "ok") {
|
|
6748
|
+
return cacheSalesNavigatorExportSessionOverride(queryUrl, {
|
|
6749
|
+
sessionCookie: normalizeSalesNavigatorSessionCookieForPhantombuster(localExtensionConfig.cookie),
|
|
6750
|
+
selectedSessionCookieSha256,
|
|
6751
|
+
source: "chrome_extension"
|
|
6752
|
+
});
|
|
6753
|
+
}
|
|
6754
|
+
}
|
|
6755
|
+
const claimed = await claimValidatedSalesNavigatorSessionCookieForCli({
|
|
6756
|
+
queryUrl,
|
|
6757
|
+
source: options.source,
|
|
6758
|
+
env: process.env
|
|
6759
|
+
});
|
|
6760
|
+
if (claimed?.sessionCookie) {
|
|
6761
|
+
return cacheSalesNavigatorExportSessionOverride(queryUrl, {
|
|
6762
|
+
sessionCookie: normalizeSalesNavigatorSessionCookieForPhantombuster(claimed.sessionCookie),
|
|
6763
|
+
selectedSessionCookieSha256: claimed.sessionCookieSha256 ??
|
|
6764
|
+
hashSalesNavigatorSessionCookieForPhantombuster(claimed.sessionCookie),
|
|
6765
|
+
source: "session_vault"
|
|
6766
|
+
});
|
|
6767
|
+
}
|
|
6768
|
+
if (localExtensionConfig?.cookie &&
|
|
6769
|
+
process.env.SALESPROMPTER_SALESNAV_EXPORT_REQUIRE_FRESH_SESSION === "1") {
|
|
6770
|
+
throw new Error("The local Salesprompter Chrome extension session cookie is not valid for Sales Navigator. Reconnect the extension, then retry the CLI command.");
|
|
6771
|
+
}
|
|
6772
|
+
if (process.env.SALESPROMPTER_CLI_MANAGE_LINKEDIN_SESSIONS === "1") {
|
|
6773
|
+
throw new Error("No validated LinkedIn Sales Navigator session cookie is available from the CLI-managed session pool.");
|
|
6774
|
+
}
|
|
6775
|
+
return null;
|
|
6776
|
+
}
|
|
6689
6777
|
async function ensureSalesNavigatorSessionPoolReady(queryUrl, options) {
|
|
6690
6778
|
try {
|
|
6691
6779
|
await options.logger?.log("salesnav.session_pool.preflight.started", {
|
|
6692
6780
|
source: options.source,
|
|
6693
6781
|
queryUrl
|
|
6694
6782
|
});
|
|
6695
|
-
const claimed = await
|
|
6696
|
-
queryUrl,
|
|
6697
|
-
source: options.source,
|
|
6698
|
-
env: process.env
|
|
6699
|
-
});
|
|
6783
|
+
const claimed = await resolveSalesNavigatorExportSessionOverride(queryUrl, options);
|
|
6700
6784
|
await options.logger?.log("salesnav.session_pool.preflight.completed", {
|
|
6701
6785
|
source: options.source,
|
|
6702
6786
|
queryUrl,
|
|
6703
6787
|
status: claimed ? "ok" : "skipped",
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
selectedSessionCookieSha256: claimed?.sessionCookieSha256 ?? null,
|
|
6707
|
-
selectedSessionLastIngestedSource: claimed?.lastIngestedSource ?? null
|
|
6788
|
+
selectedSessionSource: claimed?.source ?? "app_managed",
|
|
6789
|
+
selectedSessionCookieSha256: claimed?.selectedSessionCookieSha256 ?? null
|
|
6708
6790
|
});
|
|
6709
6791
|
return {
|
|
6710
6792
|
ready: true
|
package/package.json
CHANGED