salesprompter-cli 0.1.54 → 0.1.55
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/README.md +11 -0
- package/dist/cli.js +66 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -110,6 +110,17 @@ salesprompter packs:list
|
|
|
110
110
|
salesprompter --help
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
+
Download stored workspace leads without starting a new Sales Navigator scrape:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
salesprompter leads:download --out ./salesprompter-leads.csv
|
|
117
|
+
salesprompter leads:download --run-id <uuid> --emails-only --out ./run-leads.csv
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Use `--search <value>` to match a person, title, or company. The command uses the
|
|
121
|
+
active Salesprompter workspace and downloads the same filtered data available in
|
|
122
|
+
the app's CLI imports view.
|
|
123
|
+
|
|
113
124
|
## Output modes
|
|
114
125
|
|
|
115
126
|
- `--json` for machine-readable output
|
package/dist/cli.js
CHANGED
|
@@ -526,6 +526,7 @@ const cliPacks = [
|
|
|
526
526
|
commands: [
|
|
527
527
|
"leads:discover",
|
|
528
528
|
"leads:collect",
|
|
529
|
+
"leads:download",
|
|
529
530
|
"leads:enrich-import",
|
|
530
531
|
"search:run",
|
|
531
532
|
"search:status",
|
|
@@ -587,6 +588,7 @@ const helpVisibleCommandNames = new Set([
|
|
|
587
588
|
"wizard",
|
|
588
589
|
"auth:whoami",
|
|
589
590
|
"llm:ready",
|
|
591
|
+
"leads:download",
|
|
590
592
|
"contacts:find-linkedin-urls",
|
|
591
593
|
"companies:find-linkedin-urls",
|
|
592
594
|
"contacts:process-emails",
|
|
@@ -6757,6 +6759,59 @@ async function runCliImportEnrichmentAction(session, body, schema) {
|
|
|
6757
6759
|
}), schema);
|
|
6758
6760
|
return value;
|
|
6759
6761
|
}
|
|
6762
|
+
function parseDownloadFilename(contentDisposition) {
|
|
6763
|
+
const match = contentDisposition?.match(/filename="?([^";]+)"?/i);
|
|
6764
|
+
return match?.[1]?.trim() || `salesprompter-leads-${new Date().toISOString().slice(0, 10)}.csv`;
|
|
6765
|
+
}
|
|
6766
|
+
async function runLeadsDownloadCommand(options) {
|
|
6767
|
+
const session = await requireAuthSession();
|
|
6768
|
+
const runId = options.runId ? z.string().uuid().parse(options.runId) : null;
|
|
6769
|
+
const search = options.search?.trim() || null;
|
|
6770
|
+
const { value } = await withRefreshableAuthSession(session, async (currentSession) => {
|
|
6771
|
+
const url = new URL('/api/cli/leads/imports/export', currentSession.apiBaseUrl);
|
|
6772
|
+
if (runId)
|
|
6773
|
+
url.searchParams.set('runId', runId);
|
|
6774
|
+
if (search)
|
|
6775
|
+
url.searchParams.set('q', search);
|
|
6776
|
+
if (options.emailsOnly)
|
|
6777
|
+
url.searchParams.set('emailsOnly', '1');
|
|
6778
|
+
const response = await fetch(url, {
|
|
6779
|
+
headers: { Authorization: `Bearer ${currentSession.accessToken}` },
|
|
6780
|
+
});
|
|
6781
|
+
if (!response.ok) {
|
|
6782
|
+
const raw = await response.text();
|
|
6783
|
+
let message = `lead download failed (${response.status})`;
|
|
6784
|
+
try {
|
|
6785
|
+
const payload = JSON.parse(raw);
|
|
6786
|
+
if (typeof payload.error === 'string')
|
|
6787
|
+
message = payload.error;
|
|
6788
|
+
}
|
|
6789
|
+
catch {
|
|
6790
|
+
if (raw.trim())
|
|
6791
|
+
message = raw.trim();
|
|
6792
|
+
}
|
|
6793
|
+
throw new CliApiRequestError(message, { statusCode: response.status });
|
|
6794
|
+
}
|
|
6795
|
+
const countHeader = response.headers.get('x-salesprompter-lead-count');
|
|
6796
|
+
return {
|
|
6797
|
+
bytes: Buffer.from(await response.arrayBuffer()),
|
|
6798
|
+
count: countHeader == null ? null : Number.parseInt(countHeader, 10),
|
|
6799
|
+
filename: parseDownloadFilename(response.headers.get('content-disposition')),
|
|
6800
|
+
};
|
|
6801
|
+
});
|
|
6802
|
+
const outputPath = path.resolve(options.out?.trim() || value.filename);
|
|
6803
|
+
await mkdir(path.dirname(outputPath), { recursive: true });
|
|
6804
|
+
await writeFile(outputPath, value.bytes);
|
|
6805
|
+
return {
|
|
6806
|
+
status: 'ok',
|
|
6807
|
+
output: outputPath,
|
|
6808
|
+
leads: Number.isFinite(value.count) ? value.count : null,
|
|
6809
|
+
bytes: value.bytes.length,
|
|
6810
|
+
runId,
|
|
6811
|
+
search,
|
|
6812
|
+
emailsOnly: options.emailsOnly,
|
|
6813
|
+
};
|
|
6814
|
+
}
|
|
6760
6815
|
async function getCliImportCompanyCandidatesViaApp(session, input) {
|
|
6761
6816
|
return runCliImportEnrichmentAction(session, {
|
|
6762
6817
|
action: "company-candidates",
|
|
@@ -14284,6 +14339,17 @@ program
|
|
|
14284
14339
|
.action(async (options) => {
|
|
14285
14340
|
printOutput(await runSalesNavigatorPeopleCollectCommand(options));
|
|
14286
14341
|
});
|
|
14342
|
+
program
|
|
14343
|
+
.command("leads:download")
|
|
14344
|
+
.alias("leads:export-csv")
|
|
14345
|
+
.description("Download stored leads from the active Salesprompter workspace as CSV.")
|
|
14346
|
+
.option("--run-id <uuid>", "Limit the CSV to one CLI import run")
|
|
14347
|
+
.option("--search <value>", "Filter by person, title, or company")
|
|
14348
|
+
.option("--emails-only", "Include only leads with a found email", false)
|
|
14349
|
+
.option("--out <path>", "CSV output path; defaults to a dated filename")
|
|
14350
|
+
.action(async (options) => {
|
|
14351
|
+
printOutput(await runLeadsDownloadCommand(options));
|
|
14352
|
+
});
|
|
14287
14353
|
program
|
|
14288
14354
|
.command("salesnav:people:enrich")
|
|
14289
14355
|
.alias("leads:enrich-import")
|
package/package.json
CHANGED