@curviate/cli 0.14.0 → 0.15.1

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 (31) hide show
  1. package/CHANGELOG.md +161 -0
  2. package/README.md +52 -79
  3. package/dist/{account-7AUDAMIK.js → account-FM473HEK.js} +38 -371
  4. package/dist/{chunk-SSPILTKF.js → chunk-45KHSWCV.js} +56 -48
  5. package/dist/chunk-BGZW6B7G.js +59 -0
  6. package/dist/chunk-EEMJDJ4W.js +80 -0
  7. package/dist/{chunk-JXF47TRY.js → chunk-M33MI53G.js} +33 -1
  8. package/dist/chunk-QJZ3LWOX.js +24 -0
  9. package/dist/{chunk-4JHGVY7R.js → chunk-TMU3CSPR.js} +4 -0
  10. package/dist/{chunk-HMAGEMF7.js → chunk-ZE7QGR3F.js} +4 -0
  11. package/dist/cli.js +127 -15
  12. package/dist/comment-NCDXERSI.js +555 -0
  13. package/dist/{company-RU2CA5DY.js → company-IYTMW64G.js} +27 -74
  14. package/dist/{config-Q2AEWSEC.js → config-P5CPF5WC.js} +1 -1
  15. package/dist/{connect-QT6ZOS75.js → connect-TTJHMBUP.js} +91 -45
  16. package/dist/{exit-codes-ZTY2NY3X.js → exit-codes-SL3GQF7W.js} +1 -1
  17. package/dist/{inbox-DN7X7CM2.js → inbox-EOOGJ3ZN.js} +55 -124
  18. package/dist/job-YARGTHUY.js +631 -0
  19. package/dist/{login-BBVQLXM7.js → login-MFB45PVZ.js} +1 -1
  20. package/dist/{message-6K5E3CUF.js → message-2DLIQIE6.js} +61 -51
  21. package/dist/{post-2JQZ3OSF.js → post-GRIJ7X52.js} +188 -221
  22. package/dist/profile-57RJEL7H.js +809 -0
  23. package/dist/{recruiter-XHVMQWK6.js → recruiter-CTYH7AYG.js} +740 -226
  24. package/dist/{sales-nav-QTSTJMKA.js → sales-nav-NUMEYOEO.js} +119 -77
  25. package/dist/{search-ZGTS45BT.js → search-RD4TXNV7.js} +103 -39
  26. package/dist/{webhook-EIY5WWTE.js → webhook-CEP7SGP5.js} +8 -45
  27. package/package.json +4 -3
  28. package/dist/chunk-GXTZION6.js +0 -45
  29. package/dist/chunk-Q43HZUN3.js +0 -29
  30. package/dist/job-FGGQEXSU.js +0 -105
  31. package/dist/profile-DD5GMGNL.js +0 -501
@@ -7,29 +7,31 @@ import {
7
7
  } from "./chunk-42VUUKQ3.js";
8
8
  import {
9
9
  AttachError,
10
- readAttachment
11
- } from "./chunk-Q43HZUN3.js";
10
+ readAttachment,
11
+ toAttachmentPayload
12
+ } from "./chunk-BGZW6B7G.js";
12
13
  import {
13
14
  buildPreviewOutput
14
15
  } from "./chunk-R3VLWLVV.js";
15
- import {
16
- streamAll
17
- } from "./chunk-GXTZION6.js";
18
16
  import {
19
17
  resolveIdentifier
20
18
  } from "./chunk-DMQZEPQE.js";
19
+ import {
20
+ pageDelayFromFlags,
21
+ streamAll
22
+ } from "./chunk-EEMJDJ4W.js";
21
23
  import {
22
24
  createClient,
23
25
  renderError,
24
26
  renderSuccess,
25
27
  renderUnexpectedError,
26
28
  resolveEffectiveConfig
27
- } from "./chunk-JXF47TRY.js";
29
+ } from "./chunk-M33MI53G.js";
28
30
  import {
29
31
  GLOBAL_FLAGS,
30
32
  READ_SINGLE_FLAGS,
31
33
  WRITE_FLAGS
32
- } from "./chunk-4JHGVY7R.js";
34
+ } from "./chunk-TMU3CSPR.js";
33
35
 
34
36
  // src/commands/sales-nav.ts
35
37
  import { defineCommand } from "citty";
@@ -66,28 +68,13 @@ function normalizeAttachPaths(attach) {
66
68
  async function handleSdkError(err, outOpts, out) {
67
69
  const { CurviateError } = await import("@curviate/sdk");
68
70
  if (err instanceof CurviateError) {
69
- const { getExitCode } = await import("./exit-codes-ZTY2NY3X.js");
71
+ const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
70
72
  renderError(err, outOpts, out);
71
73
  process.exit(getExitCode(err.code));
72
74
  }
73
75
  renderUnexpectedError(err, out);
74
76
  process.exit(1);
75
77
  }
76
- async function runSalesNavSync(client, flags, out) {
77
- rejectPreviewOnRead(flags.preview, out);
78
- const accountId = requireAccount(flags.account, out);
79
- const ns = client.account(accountId);
80
- const outOpts = resolveOutputOpts(flags);
81
- const params = {};
82
- if (flags.cursor) params["cursor"] = flags.cursor;
83
- if (flags.limit) params["limit"] = parseInt(flags.limit, 10);
84
- try {
85
- const result = await ns.salesNavigator.syncMessages(params);
86
- renderSuccess(result, outOpts, out);
87
- } catch (err) {
88
- await handleSdkError(err, outOpts, out);
89
- }
90
- }
91
78
  async function runSalesNavSearchPeople(client, flags, out, readers = DEFAULT_FILTER_READERS) {
92
79
  rejectPreviewOnRead(flags.preview, out);
93
80
  const accountId = requireAccount(flags.account, out);
@@ -125,8 +112,8 @@ async function runSalesNavSearchPeople(client, flags, out, readers = DEFAULT_FIL
125
112
  };
126
113
  for await (const item of streamAll(fn, params, {
127
114
  maxPages,
128
- onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
129
- `)
115
+ out,
116
+ pageDelayMs: pageDelayFromFlags(flags)
130
117
  })) {
131
118
  out.stdout.write(JSON.stringify(item) + "\n");
132
119
  }
@@ -174,8 +161,8 @@ async function runSalesNavSearchCompanies(client, flags, out, readers = DEFAULT_
174
161
  };
175
162
  for await (const item of streamAll(fn, params, {
176
163
  maxPages,
177
- onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
178
- `)
164
+ out,
165
+ pageDelayMs: pageDelayFromFlags(flags)
179
166
  })) {
180
167
  out.stdout.write(JSON.stringify(item) + "\n");
181
168
  }
@@ -189,13 +176,16 @@ async function runSalesNavSearchCompanies(client, flags, out, readers = DEFAULT_
189
176
  }
190
177
  async function runSalesNavGetParameters(client, flags, out) {
191
178
  rejectPreviewOnRead(flags.preview, out);
179
+ if (!flags.type) {
180
+ out.stderr.write("error: --type is required.\n");
181
+ process.exit(2);
182
+ }
192
183
  const accountId = requireAccount(flags.account, out);
193
184
  const ns = client.account(accountId);
194
185
  const outOpts = resolveOutputOpts(flags);
195
- const params = {};
196
- if (flags.type) params["type"] = flags.type;
197
- if (flags.keywords) params["keywords"] = flags.keywords;
198
- if (flags.limit) params["limit"] = parseInt(flags.limit, 10);
186
+ const params = { type: flags.type };
187
+ if (flags.keywords) params.keywords = flags.keywords;
188
+ if (flags.limit) params.limit = parseInt(flags.limit, 10);
199
189
  try {
200
190
  const result = await ns.salesNavigator.getParameters(params);
201
191
  renderSuccess(result, outOpts, out);
@@ -203,13 +193,57 @@ async function runSalesNavGetParameters(client, flags, out) {
203
193
  await handleSdkError(err, outOpts, out);
204
194
  }
205
195
  }
196
+ async function runSalesNavSearchFromUrl(client, flags, out) {
197
+ rejectPreviewOnRead(flags.preview, out);
198
+ const accountId = requireAccount(flags.account, out);
199
+ const url = flags.url ?? "";
200
+ const ns = client.account(accountId);
201
+ const outOpts = resolveOutputOpts(flags);
202
+ const all = flags.all ?? false;
203
+ const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
204
+ const limit = flags.limit ? parseInt(flags.limit, 10) : void 0;
205
+ const cursor = flags.cursor;
206
+ const body = { url };
207
+ const params = {};
208
+ if (limit !== void 0) params["limit"] = limit;
209
+ if (cursor) params["cursor"] = cursor;
210
+ try {
211
+ if (all) {
212
+ const fn = (p) => {
213
+ const { cursor: c, limit: l, ...restP } = p;
214
+ const callParams = {};
215
+ if (c) callParams["cursor"] = c;
216
+ if (l) callParams["limit"] = l;
217
+ void restP;
218
+ return ns.salesNavigator.searchFromUrl(body, callParams);
219
+ };
220
+ for await (const item of streamAll(fn, params, {
221
+ maxPages,
222
+ out,
223
+ pageDelayMs: pageDelayFromFlags(flags)
224
+ })) {
225
+ out.stdout.write(JSON.stringify(item) + "\n");
226
+ }
227
+ } else {
228
+ const result = await ns.salesNavigator.searchFromUrl(body, Object.keys(params).length > 0 ? params : void 0);
229
+ renderSuccess(result, outOpts, out);
230
+ }
231
+ } catch (err) {
232
+ await handleSdkError(err, outOpts, out);
233
+ }
234
+ }
206
235
  async function runSalesNavMessageNew(client, flags, out) {
207
236
  const accountId = requireAccount(flags.account, out);
208
237
  const to = flags.to ?? "";
209
238
  const text = flags.text ?? "";
239
+ const subject = flags.subject ?? "";
210
240
  const attachPaths = normalizeAttachPaths(flags.attach);
211
241
  const voicePath = flags.voice;
212
242
  const videoPath = flags.video;
243
+ if (!subject) {
244
+ out.stderr.write("error: --subject is required (v2: REQUIRED for Sales Navigator messaging).\n");
245
+ process.exit(2);
246
+ }
213
247
  let attachBuffers = [];
214
248
  let voiceBuffer;
215
249
  let videoBuffer;
@@ -225,15 +259,11 @@ async function runSalesNavMessageNew(client, flags, out) {
225
259
  }
226
260
  throw err;
227
261
  }
228
- const body = {
229
- attendees_ids: [to],
230
- text
231
- };
232
262
  if (flags.preview) {
233
263
  const preview = buildPreviewOutput({
234
264
  method: "salesNavigator.startChat",
235
265
  args: { attendees_ids: [to] },
236
- body: { ...body },
266
+ body: { attendees_ids: [to], text, subject },
237
267
  account: accountId,
238
268
  attachments: [
239
269
  ...attachBuffers.map((buf, i) => ({
@@ -247,9 +277,17 @@ async function runSalesNavMessageNew(client, flags, out) {
247
277
  out.stdout.write(JSON.stringify(preview) + "\n");
248
278
  return;
249
279
  }
250
- if (attachBuffers.length > 0) body["attachments"] = attachBuffers;
251
- if (voiceBuffer) body["voice_message"] = voiceBuffer;
252
- if (videoBuffer) body["video_message"] = videoBuffer;
280
+ const attachments = [
281
+ ...attachPaths.map((p, i) => toAttachmentPayload(p, attachBuffers[i])),
282
+ ...voiceBuffer && voicePath ? [{ ...toAttachmentPayload(voicePath, voiceBuffer), send_mode: "native" }] : [],
283
+ ...videoBuffer && videoPath ? [{ ...toAttachmentPayload(videoPath, videoBuffer), send_mode: "native" }] : []
284
+ ];
285
+ const body = {
286
+ attendees_ids: [to],
287
+ text,
288
+ subject,
289
+ ...attachments.length > 0 ? { attachments } : {}
290
+ };
253
291
  const ns = client.account(accountId);
254
292
  const outOpts = resolveOutputOpts(flags);
255
293
  try {
@@ -312,8 +350,8 @@ async function runSalesNavAccountLists(client, flags, out) {
312
350
  const fn = (p) => ns.salesNavigator.accountLists(p);
313
351
  for await (const item of streamAll(fn, params, {
314
352
  maxPages,
315
- onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
316
- `)
353
+ out,
354
+ pageDelayMs: pageDelayFromFlags(flags)
317
355
  })) {
318
356
  out.stdout.write(JSON.stringify(item) + "\n");
319
357
  }
@@ -340,8 +378,8 @@ async function runSalesNavLeadLists(client, flags, out) {
340
378
  const fn = (p) => ns.salesNavigator.leadLists(p);
341
379
  for await (const item of streamAll(fn, params, {
342
380
  maxPages,
343
- onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
344
- `)
381
+ out,
382
+ pageDelayMs: pageDelayFromFlags(flags)
345
383
  })) {
346
384
  out.stdout.write(JSON.stringify(item) + "\n");
347
385
  }
@@ -373,8 +411,8 @@ async function runSalesNavBrowseAccountList(client, flags, out) {
373
411
  const fn = (p) => ns.salesNavigator.browseAccountList(listId, body, p);
374
412
  for await (const item of streamAll(fn, params, {
375
413
  maxPages,
376
- onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
377
- `)
414
+ out,
415
+ pageDelayMs: pageDelayFromFlags(flags)
378
416
  })) {
379
417
  out.stdout.write(JSON.stringify(item) + "\n");
380
418
  }
@@ -406,8 +444,8 @@ async function runSalesNavBrowseLeadList(client, flags, out) {
406
444
  const fn = (p) => ns.salesNavigator.browseLeadList(listId, body, p);
407
445
  for await (const item of streamAll(fn, params, {
408
446
  maxPages,
409
- onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
410
- `)
447
+ out,
448
+ pageDelayMs: pageDelayFromFlags(flags)
411
449
  })) {
412
450
  out.stdout.write(JSON.stringify(item) + "\n");
413
451
  }
@@ -443,27 +481,6 @@ async function runSalesNavSaveAccount(client, flags, out) {
443
481
  await handleSdkError(err, outOpts, out);
444
482
  }
445
483
  }
446
- var salesNavSyncCommand = defineCommand({
447
- meta: { name: "sync", description: "Sync Sales Navigator message history for an account." },
448
- args: { ...GLOBAL_FLAGS },
449
- async run({ args }) {
450
- const flags = args;
451
- const cfg = await resolveEffectiveConfig({
452
- apiKey: flags["api-key"],
453
- baseUrl: flags["base-url"],
454
- timeout: flags.timeout,
455
- account: flags.account,
456
- profile: flags.profile
457
- });
458
- if (!cfg.apiKey) {
459
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
460
- process.exit(3);
461
- }
462
- const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
463
- const out = buildOutputStreams();
464
- await runSalesNavSync(client, { ...flags, account: flags.account ?? cfg.account }, out);
465
- }
466
- });
467
484
  var salesNavMessageNewCommand = defineCommand({
468
485
  meta: { name: "new", description: "Start a new Sales Navigator chat." },
469
486
  args: {
@@ -474,6 +491,7 @@ var salesNavMessageNewCommand = defineCommand({
474
491
  description: "Recipient's LinkedIn provider ID (ACw\u2026 format, e.g. from a Sales Navigator search result or profile). Not resolved from a URL/slug \u2014 pass the provider ID directly.",
475
492
  required: true
476
493
  },
494
+ subject: { type: "string", description: "Message subject line (required for Sales Navigator messaging).", required: true },
477
495
  text: { type: "positional", description: "Opening message text." },
478
496
  attach: { type: "string", description: "File to attach (repeatable, max 7 MiB each)." },
479
497
  voice: { type: "string", description: "Voice message file (max 7 MiB)." },
@@ -596,17 +614,42 @@ var salesNavSearchParametersCommand = defineCommand({
596
614
  }
597
615
  });
598
616
  var salesNavSearchCommand = defineCommand({
599
- meta: { name: "search", description: "Sales Navigator search operations." },
600
- args: { ...GLOBAL_FLAGS },
617
+ meta: { name: "search", description: "Sales Navigator search operations. Also runs a pasted Sales Navigator search/list URL directly." },
618
+ args: {
619
+ ...GLOBAL_FLAGS,
620
+ url: {
621
+ type: "positional",
622
+ required: false,
623
+ description: "A pasted Sales Navigator search or list URL. Runs it directly (salesNavigator.searchFromUrl)."
624
+ }
625
+ },
601
626
  subCommands: {
602
627
  people: salesNavSearchPeopleCommand,
603
628
  companies: salesNavSearchCompaniesCommand,
604
629
  parameters: salesNavSearchParametersCommand
605
630
  },
606
- async run() {
607
- process.stderr.write(
608
- "Usage: curviate sales-nav search people [--keywords <k>]\n curviate sales-nav search companies [--keywords <k>]\n curviate sales-nav search parameters --type <t>\n"
609
- );
631
+ async run({ args }) {
632
+ const flags = args;
633
+ if (!flags.url) {
634
+ process.stderr.write(
635
+ "Usage: curviate sales-nav search <url>\n curviate sales-nav search people [--keywords <k>]\n curviate sales-nav search companies [--keywords <k>]\n curviate sales-nav search parameters --type <t>\n"
636
+ );
637
+ return;
638
+ }
639
+ const cfg = await resolveEffectiveConfig({
640
+ apiKey: flags["api-key"],
641
+ baseUrl: flags["base-url"],
642
+ timeout: flags.timeout,
643
+ account: flags.account,
644
+ profile: flags.profile
645
+ });
646
+ if (!cfg.apiKey) {
647
+ process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
648
+ process.exit(3);
649
+ }
650
+ const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
651
+ const out = buildOutputStreams();
652
+ await runSalesNavSearchFromUrl(client, { ...flags, account: flags.account ?? cfg.account }, out);
610
653
  }
611
654
  });
612
655
  var salesNavProfileCommand = defineCommand({
@@ -786,7 +829,6 @@ var salesNavCommand = defineCommand({
786
829
  meta: { name: "sales-nav", description: "Sales Navigator operations (requires the Sales Navigator add-on)." },
787
830
  args: { ...GLOBAL_FLAGS },
788
831
  subCommands: {
789
- sync: salesNavSyncCommand,
790
832
  message: salesNavMessageCommand,
791
833
  search: salesNavSearchCommand,
792
834
  profile: salesNavProfileCommand,
@@ -799,7 +841,7 @@ var salesNavCommand = defineCommand({
799
841
  },
800
842
  async run() {
801
843
  process.stderr.write(
802
- 'Usage: curviate sales-nav sync\n curviate sales-nav search people [--keywords <k>]\n curviate sales-nav search companies [--keywords <k>]\n curviate sales-nav search parameters --type <t>\n curviate sales-nav message new --to <id> "<text>"\n curviate sales-nav profile <identifier>\n curviate sales-nav save-lead --list <id> <user_id>\n curviate sales-nav account-lists --account <id>\n curviate sales-nav lead-lists --account <id>\n curviate sales-nav browse-account-list <list_id> --account <id>\n curviate sales-nav browse-lead-list <list_id> --account <id>\n curviate sales-nav save-account --list <id> <company_id> --account <id>\n'
844
+ 'Usage: curviate sales-nav search people [--keywords <k>]\n curviate sales-nav search companies [--keywords <k>]\n curviate sales-nav search parameters --type <t>\n curviate sales-nav search <url>\n curviate sales-nav message new --to <id> "<text>"\n curviate sales-nav profile <identifier>\n curviate sales-nav save-lead --list <id> <user_id>\n curviate sales-nav account-lists --account <id>\n curviate sales-nav lead-lists --account <id>\n curviate sales-nav browse-account-list <list_id> --account <id>\n curviate sales-nav browse-lead-list <list_id> --account <id>\n curviate sales-nav save-account --list <id> <company_id> --account <id>\n'
803
845
  );
804
846
  }
805
847
  });
@@ -814,7 +856,7 @@ export {
814
856
  runSalesNavSaveAccount,
815
857
  runSalesNavSaveLead,
816
858
  runSalesNavSearchCompanies,
859
+ runSalesNavSearchFromUrl,
817
860
  runSalesNavSearchPeople,
818
- runSalesNavSync,
819
861
  salesNavCommand
820
862
  };
@@ -5,9 +5,6 @@ import {
5
5
  splitCsv,
6
6
  splitCsvNumbers
7
7
  } from "./chunk-42VUUKQ3.js";
8
- import {
9
- streamAll
10
- } from "./chunk-GXTZION6.js";
11
8
  import {
12
9
  slimSearchCompanies,
13
10
  slimSearchCompaniesItem,
@@ -17,17 +14,21 @@ import {
17
14
  slimSearchPeopleItem,
18
15
  slimSearchPosts,
19
16
  slimSearchPostsItem
20
- } from "./chunk-SSPILTKF.js";
17
+ } from "./chunk-45KHSWCV.js";
18
+ import {
19
+ pageDelayFromFlags,
20
+ streamAll
21
+ } from "./chunk-EEMJDJ4W.js";
21
22
  import {
22
23
  createClient,
23
24
  renderError,
24
25
  renderSuccess,
25
26
  renderUnexpectedError,
26
27
  resolveEffectiveConfig
27
- } from "./chunk-JXF47TRY.js";
28
+ } from "./chunk-M33MI53G.js";
28
29
  import {
29
30
  GLOBAL_FLAGS
30
- } from "./chunk-4JHGVY7R.js";
31
+ } from "./chunk-TMU3CSPR.js";
31
32
 
32
33
  // src/commands/search.ts
33
34
  import { defineCommand } from "citty";
@@ -86,7 +87,6 @@ function resolveOutputOpts(flags) {
86
87
  }
87
88
  function applyCommonSearchFlags(body, flags) {
88
89
  if (flags.keywords) body["keywords"] = flags.keywords;
89
- if (flags.url) body["url"] = flags.url;
90
90
  if (flags.cursor) body["cursor"] = flags.cursor;
91
91
  if (flags.limit) body["limit"] = parseInt(flags.limit, 10);
92
92
  }
@@ -207,10 +207,8 @@ async function runSearchPeople(client, flags, out, readers = DEFAULT_FILTER_READ
207
207
  const fn = (p) => ns.search.people(p);
208
208
  for await (const item of streamAll(fn, body, {
209
209
  maxPages,
210
- // Write JSON truncation sentinel to stdout as the last NDJSON line
211
- onTruncated: (pagesFetched, hasMore) => out.stdout.write(
212
- JSON.stringify({ object: "stream_truncated", pages_fetched: pagesFetched, has_more: hasMore }) + "\n"
213
- )
210
+ out,
211
+ pageDelayMs: pageDelayFromFlags(flags)
214
212
  })) {
215
213
  const projected = verbose ? item : slimSearchPeopleItem(item);
216
214
  out.stdout.write(JSON.stringify(projected) + "\n");
@@ -222,7 +220,7 @@ async function runSearchPeople(client, flags, out, readers = DEFAULT_FILTER_READ
222
220
  } catch (err) {
223
221
  const { CurviateError } = await import("@curviate/sdk");
224
222
  if (err instanceof CurviateError) {
225
- const { getExitCode } = await import("./exit-codes-ZTY2NY3X.js");
223
+ const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
226
224
  renderError(err, outOpts, out);
227
225
  process.exit(getExitCode(err.code));
228
226
  }
@@ -250,9 +248,8 @@ async function runSearchCompanies(client, flags, out, readers = DEFAULT_FILTER_R
250
248
  const fn = (p) => ns.search.companies(p);
251
249
  for await (const item of streamAll(fn, body, {
252
250
  maxPages,
253
- onTruncated: (pagesFetched, hasMore) => out.stdout.write(
254
- JSON.stringify({ object: "stream_truncated", pages_fetched: pagesFetched, has_more: hasMore }) + "\n"
255
- )
251
+ out,
252
+ pageDelayMs: pageDelayFromFlags(flags)
256
253
  })) {
257
254
  const projected = verbose ? item : slimSearchCompaniesItem(item);
258
255
  out.stdout.write(JSON.stringify(projected) + "\n");
@@ -264,7 +261,7 @@ async function runSearchCompanies(client, flags, out, readers = DEFAULT_FILTER_R
264
261
  } catch (err) {
265
262
  const { CurviateError } = await import("@curviate/sdk");
266
263
  if (err instanceof CurviateError) {
267
- const { getExitCode } = await import("./exit-codes-ZTY2NY3X.js");
264
+ const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
268
265
  renderError(err, outOpts, out);
269
266
  process.exit(getExitCode(err.code));
270
267
  }
@@ -292,9 +289,8 @@ async function runSearchPosts(client, flags, out, readers = DEFAULT_FILTER_READE
292
289
  const fn = (p) => ns.search.posts(p);
293
290
  for await (const item of streamAll(fn, body, {
294
291
  maxPages,
295
- onTruncated: (pagesFetched, hasMore) => out.stdout.write(
296
- JSON.stringify({ object: "stream_truncated", pages_fetched: pagesFetched, has_more: hasMore }) + "\n"
297
- )
292
+ out,
293
+ pageDelayMs: pageDelayFromFlags(flags)
298
294
  })) {
299
295
  const projected = verbose ? item : slimSearchPostsItem(item);
300
296
  out.stdout.write(JSON.stringify(projected) + "\n");
@@ -306,7 +302,7 @@ async function runSearchPosts(client, flags, out, readers = DEFAULT_FILTER_READE
306
302
  } catch (err) {
307
303
  const { CurviateError } = await import("@curviate/sdk");
308
304
  if (err instanceof CurviateError) {
309
- const { getExitCode } = await import("./exit-codes-ZTY2NY3X.js");
305
+ const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
310
306
  renderError(err, outOpts, out);
311
307
  process.exit(getExitCode(err.code));
312
308
  }
@@ -334,9 +330,8 @@ async function runSearchJobs(client, flags, out, readers = DEFAULT_FILTER_READER
334
330
  const fn = (p) => ns.search.jobs(p);
335
331
  for await (const item of streamAll(fn, body, {
336
332
  maxPages,
337
- onTruncated: (pagesFetched, hasMore) => out.stdout.write(
338
- JSON.stringify({ object: "stream_truncated", pages_fetched: pagesFetched, has_more: hasMore }) + "\n"
339
- )
333
+ out,
334
+ pageDelayMs: pageDelayFromFlags(flags)
340
335
  })) {
341
336
  const projected = verbose ? item : slimSearchJobsItem(item);
342
337
  out.stdout.write(JSON.stringify(projected) + "\n");
@@ -348,7 +343,7 @@ async function runSearchJobs(client, flags, out, readers = DEFAULT_FILTER_READER
348
343
  } catch (err) {
349
344
  const { CurviateError } = await import("@curviate/sdk");
350
345
  if (err instanceof CurviateError) {
351
- const { getExitCode } = await import("./exit-codes-ZTY2NY3X.js");
346
+ const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
352
347
  renderError(err, outOpts, out);
353
348
  process.exit(getExitCode(err.code));
354
349
  }
@@ -359,20 +354,66 @@ async function runSearchJobs(client, flags, out, readers = DEFAULT_FILTER_READER
359
354
  async function runSearchParameters(client, flags, out) {
360
355
  rejectPreviewOnRead(flags.preview, out);
361
356
  rejectAllOnNonPaginated(flags.all, out);
357
+ if (!flags.type) {
358
+ out.stderr.write("error: --type is required.\n");
359
+ process.exit(2);
360
+ }
361
+ if (!flags.keywords) {
362
+ out.stderr.write("error: --keywords is required (v2: required for every --type).\n");
363
+ process.exit(2);
364
+ }
362
365
  const accountId = requireAccount(flags.account, out);
363
366
  const ns = client.account(accountId);
364
367
  const outOpts = resolveOutputOpts(flags);
365
- const query = {};
366
- if (flags.type) query["type"] = flags.type;
367
- if (flags.keywords) query["keywords"] = flags.keywords;
368
- if (flags.limit) query["limit"] = parseInt(flags.limit, 10);
368
+ const query = {
369
+ type: flags.type,
370
+ keywords: flags.keywords
371
+ };
372
+ if (flags.limit) query.limit = parseInt(flags.limit, 10);
369
373
  try {
370
374
  const result = await ns.search.getParameters(query);
371
375
  renderSuccess(result, outOpts, out);
372
376
  } catch (err) {
373
377
  const { CurviateError } = await import("@curviate/sdk");
374
378
  if (err instanceof CurviateError) {
375
- const { getExitCode } = await import("./exit-codes-ZTY2NY3X.js");
379
+ const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
380
+ renderError(err, outOpts, out);
381
+ process.exit(getExitCode(err.code));
382
+ }
383
+ renderUnexpectedError(err, out);
384
+ process.exit(1);
385
+ }
386
+ }
387
+ async function runSearchFromUrl(client, flags, out) {
388
+ rejectPreviewOnRead(flags.preview, out);
389
+ const accountId = requireAccount(flags.account, out);
390
+ const url = flags.url ?? "";
391
+ const ns = client.account(accountId);
392
+ const outOpts = resolveOutputOpts(flags);
393
+ const verbose = flags.verbose ?? false;
394
+ const all = flags.all ?? false;
395
+ const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
396
+ const body = { url };
397
+ if (flags.limit) body.limit = parseInt(flags.limit, 10);
398
+ if (flags.cursor) body.cursor = flags.cursor;
399
+ try {
400
+ if (all) {
401
+ const fn = (p) => ns.search.fromUrl(p);
402
+ for await (const item of streamAll(fn, body, {
403
+ maxPages,
404
+ out,
405
+ pageDelayMs: pageDelayFromFlags(flags)
406
+ })) {
407
+ out.stdout.write(JSON.stringify(item) + "\n");
408
+ }
409
+ } else {
410
+ const result = await ns.search.fromUrl(body);
411
+ renderSuccess(result, { ...outOpts, verbose }, out);
412
+ }
413
+ } catch (err) {
414
+ const { CurviateError } = await import("@curviate/sdk");
415
+ if (err instanceof CurviateError) {
416
+ const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
376
417
  renderError(err, outOpts, out);
377
418
  process.exit(getExitCode(err.code));
378
419
  }
@@ -385,7 +426,6 @@ var searchPeopleCommand = defineCommand({
385
426
  args: {
386
427
  ...GLOBAL_FLAGS,
387
428
  keywords: { type: "string", description: "Full-text keyword search." },
388
- url: { type: "string", description: "Pasted LinkedIn search URL (mutually exclusive with filters)." },
389
429
  ...FILTER_FLAGS,
390
430
  industry: { type: "string", description: "Industry ids (comma-separated)." },
391
431
  location: { type: "string", description: "Location ids (comma-separated)." },
@@ -422,7 +462,6 @@ var searchCompaniesCommand = defineCommand({
422
462
  args: {
423
463
  ...GLOBAL_FLAGS,
424
464
  keywords: { type: "string", description: "Full-text keyword search." },
425
- url: { type: "string", description: "Pasted LinkedIn search URL (mutually exclusive with filters)." },
426
465
  ...FILTER_FLAGS,
427
466
  industry: { type: "string", description: "Industry ids (comma-separated)." },
428
467
  location: { type: "string", description: "Location ids (comma-separated)." },
@@ -456,7 +495,6 @@ var searchPostsCommand = defineCommand({
456
495
  args: {
457
496
  ...GLOBAL_FLAGS,
458
497
  keywords: { type: "string", description: "Full-text keyword search." },
459
- url: { type: "string", description: "Pasted LinkedIn search URL (mutually exclusive with filters)." },
460
498
  ...FILTER_FLAGS,
461
499
  "sort-by": { type: "string", description: "Sort order (e.g. relevance, date)." },
462
500
  "date-posted": { type: "string", description: "time window: past_day, past_week, or past_month (hyphens also accepted: past-day, past-week, past-month)" },
@@ -493,7 +531,6 @@ var searchJobsCommand = defineCommand({
493
531
  args: {
494
532
  ...GLOBAL_FLAGS,
495
533
  keywords: { type: "string", description: "Full-text keyword search." },
496
- url: { type: "string", description: "Pasted LinkedIn search URL (mutually exclusive with filters)." },
497
534
  ...FILTER_FLAGS,
498
535
  // On jobs, --location maps to the geo region filter (not a location array — different API shape for jobs vs people)
499
536
  location: { type: "string", description: "geo region id (single id; resolve via search parameters --type LOCATION); maps to region filter" },
@@ -548,7 +585,7 @@ var searchParametersCommand = defineCommand({
548
585
  description: "Parameter type: LOCATION, PEOPLE, CONNECTIONS, COMPANY, SCHOOL, INDUSTRY, SERVICE, JOB_FUNCTION, JOB_TITLE, EMPLOYMENT_TYPE, SKILL.",
549
586
  required: true
550
587
  },
551
- keywords: { type: "string", description: "Human term to resolve (not required for EMPLOYMENT_TYPE)." }
588
+ keywords: { type: "string", description: "Human term to resolve (required for every --type, incl. EMPLOYMENT_TYPE).", required: true }
552
589
  },
553
590
  async run({ args }) {
554
591
  const flags = args;
@@ -569,7 +606,15 @@ var searchParametersCommand = defineCommand({
569
606
  }
570
607
  });
571
608
  var searchCommand = defineCommand({
572
- meta: { name: "search", description: "Search people, companies, posts, and jobs." },
609
+ meta: { name: "search", description: "Search people, companies, posts, and jobs. Also runs a pasted search URL directly." },
610
+ args: {
611
+ ...GLOBAL_FLAGS,
612
+ url: {
613
+ type: "positional",
614
+ required: false,
615
+ description: "A pasted LinkedIn search, saved-search re-run, or lead-list URL. Runs it directly (search.fromUrl)."
616
+ }
617
+ },
573
618
  subCommands: {
574
619
  people: searchPeopleCommand,
575
620
  companies: searchCompaniesCommand,
@@ -577,14 +622,33 @@ var searchCommand = defineCommand({
577
622
  jobs: searchJobsCommand,
578
623
  parameters: searchParametersCommand
579
624
  },
580
- async run() {
581
- process.stderr.write(
582
- "Usage: curviate search <subcommand>\n people [--url <u>] [--keywords <k>]\n companies [--keywords <k>]\n posts [--keywords <k>]\n jobs [--keywords <k>]\n parameters --type <t> [--keywords <k>]\n"
583
- );
625
+ async run({ args }) {
626
+ const flags = args;
627
+ if (!flags.url) {
628
+ process.stderr.write(
629
+ "Usage: curviate search <url>\n curviate search people [--keywords <k>]\n curviate search companies [--keywords <k>]\n curviate search posts [--keywords <k>]\n curviate search jobs [--keywords <k>]\n curviate search parameters --type <t> --keywords <k>\n"
630
+ );
631
+ process.exit(2);
632
+ }
633
+ const cfg = await resolveEffectiveConfig({
634
+ apiKey: flags["api-key"],
635
+ baseUrl: flags["base-url"],
636
+ timeout: flags.timeout,
637
+ account: flags.account,
638
+ profile: flags.profile
639
+ });
640
+ if (!cfg.apiKey) {
641
+ process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
642
+ process.exit(3);
643
+ }
644
+ const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
645
+ const out = buildOutputStreams();
646
+ await runSearchFromUrl(client, { ...flags, account: flags.account ?? cfg.account }, out);
584
647
  }
585
648
  });
586
649
  export {
587
650
  runSearchCompanies,
651
+ runSearchFromUrl,
588
652
  runSearchJobs,
589
653
  runSearchParameters,
590
654
  runSearchPeople,