@curviate/cli 0.18.1 → 0.20.0

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 (26) hide show
  1. package/CHANGELOG.md +123 -0
  2. package/dist/{account-EGJJNBXW.js → account-2SOSCEB6.js} +26 -26
  3. package/dist/{chunk-TMU3CSPR.js → chunk-DW2HCRXJ.js} +1 -1
  4. package/dist/{chunk-M33MI53G.js → chunk-HDQUEFD2.js} +1 -1
  5. package/dist/chunk-HOQ7EUHJ.js +50 -0
  6. package/dist/{chunk-KVV6LZ7E.js → chunk-IGCQNDIG.js} +53 -17
  7. package/dist/cli.js +33 -33
  8. package/dist/{comment-VT6PO4MN.js → comment-AXDINBPS.js} +3 -3
  9. package/dist/{company-BVXX4FGX.js → company-BX4VDXZX.js} +398 -16
  10. package/dist/{config-P5CPF5WC.js → config-3O4N2XSH.js} +2 -2
  11. package/dist/{connect-6PU7QCOL.js → connect-KWOJKCIB.js} +36 -15
  12. package/dist/feed-4ROKUBG5.js +127 -0
  13. package/dist/group-L7TQEEFN.js +236 -0
  14. package/dist/{inbox-DRJ6ENXC.js → inbox-GMGZVDTQ.js} +69 -11
  15. package/dist/{inboxes-MTPWLP5F.js → inboxes-YVYLSM5W.js} +4 -4
  16. package/dist/{job-EIXBJXLW.js → job-TYBA2DUQ.js} +7 -7
  17. package/dist/{login-GDLWR542.js → login-W7NCDZOQ.js} +2 -2
  18. package/dist/{message-UWMRE2SJ.js → message-C6FV6JH6.js} +6 -3
  19. package/dist/notification-45XFT3S4.js +219 -0
  20. package/dist/{post-N3GQDIQJ.js → post-RETV3WUG.js} +102 -9
  21. package/dist/{profile-XWSRUYRW.js → profile-A2TWF4HB.js} +121 -15
  22. package/dist/{recruiter-MVPSTH2V.js → recruiter-FQAKY6Z2.js} +30 -30
  23. package/dist/{sales-nav-TMXWDKSE.js → sales-nav-SSJIZUNB.js} +16 -16
  24. package/dist/{search-ZQUKLQ6T.js → search-DH6BJFQC.js} +213 -12
  25. package/dist/{webhook-QFSZN3P2.js → webhook-LED6AKF3.js} +50 -19
  26. package/package.json +4 -4
@@ -9,11 +9,11 @@ import {
9
9
  renderSuccess,
10
10
  renderUnexpectedError,
11
11
  resolveEffectiveConfig
12
- } from "./chunk-M33MI53G.js";
12
+ } from "./chunk-HDQUEFD2.js";
13
13
  import {
14
14
  GLOBAL_FLAGS,
15
15
  READ_SINGLE_FLAGS
16
- } from "./chunk-TMU3CSPR.js";
16
+ } from "./chunk-DW2HCRXJ.js";
17
17
 
18
18
  // src/commands/inboxes.ts
19
19
  import { defineCommand } from "citty";
@@ -141,7 +141,7 @@ var inboxesListCommand = defineCommand({
141
141
  profile: flags.profile
142
142
  });
143
143
  if (!cfg.apiKey) {
144
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
144
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
145
145
  process.exit(3);
146
146
  }
147
147
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
@@ -169,7 +169,7 @@ var inboxesChatsCommand = defineCommand({
169
169
  profile: flags.profile
170
170
  });
171
171
  if (!cfg.apiKey) {
172
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
172
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
173
173
  process.exit(3);
174
174
  }
175
175
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
@@ -24,12 +24,12 @@ import {
24
24
  renderSuccess,
25
25
  renderUnexpectedError,
26
26
  resolveEffectiveConfig
27
- } from "./chunk-M33MI53G.js";
27
+ } from "./chunk-HDQUEFD2.js";
28
28
  import {
29
29
  GLOBAL_FLAGS,
30
30
  READ_SINGLE_FLAGS,
31
31
  WRITE_SINGLE_FLAGS
32
- } from "./chunk-TMU3CSPR.js";
32
+ } from "./chunk-DW2HCRXJ.js";
33
33
 
34
34
  // src/commands/job.ts
35
35
  import { defineCommand } from "citty";
@@ -181,7 +181,7 @@ async function runJobList(client, flags, out) {
181
181
  function pace(ms) {
182
182
  return ms > 0 ? new Promise((resolve) => setTimeout(resolve, ms)) : Promise.resolve();
183
183
  }
184
- var JOB_LIST_UNION_CAVEAT = "note: --state ALL is a best-effort client-side union over DRAFT/OPEN/CLOSED/REVIEW/SUSPENDED. LinkedIn's per-state filter is best-effort, so each state is queried, its items are re-filtered against their own state, and the results are merged and de-duplicated by id. There is no unified pagination cursor \u2014 each state is walked independently and --max-pages applies per state.\n";
184
+ var JOB_LIST_UNION_CAVEAT = "note: --state ALL is a best-effort client-side union over DRAFT/OPEN/CLOSED/REVIEW/SUSPENDED. LinkedIn's per-state filter is best-effort, so each state is queried, its items are re-filtered against their own state, and the results are merged and de-duplicated by id. There is no unified pagination cursor; each state is walked independently and --max-pages applies per state.\n";
185
185
  function jobItemId(item) {
186
186
  const id = item.id;
187
187
  return typeof id === "string" ? id : void 0;
@@ -453,7 +453,7 @@ async function withClient(flags, fn) {
453
453
  profile: flags.profile
454
454
  });
455
455
  if (!cfg.apiKey) {
456
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
456
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
457
457
  process.exit(3);
458
458
  }
459
459
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
@@ -468,7 +468,7 @@ var JOB_BODY_FLAGS = {
468
468
  "workplace-type": { type: "string", description: "Workplace arrangement: ON_SITE|HYBRID|REMOTE." },
469
469
  location: { type: "string", description: "A LOCATION parameter id (from search parameters)." },
470
470
  "employment-status": { type: "string", description: "Employment type: FULL_TIME|PART_TIME|CONTRACT|TEMPORARY|OTHER|VOLUNTEER|INTERNSHIP." },
471
- description: { type: "string", description: "Full job description (required; minimum 200 characters \u2014 enforced server-side)." },
471
+ description: { type: "string", description: "Full job description (required; minimum 200 characters, enforced server-side)." },
472
472
  "apply-method": { type: "string", description: "How candidates apply: linkedin|external." },
473
473
  "notification-email": { type: "string", description: "Email notified of new applicants (required when --apply-method is linkedin)." },
474
474
  "website-url": { type: "string", description: "External apply URL (required when --apply-method is external)." },
@@ -526,13 +526,13 @@ var jobBudgetCommand = defineCommand({
526
526
  }
527
527
  });
528
528
  var jobPublishCommand = defineCommand({
529
- meta: { name: "publish", description: "Publish a draft. PROMOTED/PROMOTED_PLUS spend real money and require --budget-*." },
529
+ meta: { name: "publish", description: "Publish a draft. PROMOTED/PROMOTED_PLUS spend real money and require --budget-amount, --budget-currency, and --budget-scope." },
530
530
  args: {
531
531
  ...WRITE_SINGLE_FLAGS,
532
532
  id: { type: "positional", description: "Job id to publish." },
533
533
  mode: { type: "string", description: "Publish mode (required): FREE|PROMOTED|PROMOTED_PLUS.", required: true },
534
534
  "budget-currency": { type: "string", description: "ISO-4217 currency (required for a paid publish), e.g. EUR." },
535
- "budget-amount": { type: "string", description: "Budget amount \u2014 a non-negative number (required for a paid publish)." },
535
+ "budget-amount": { type: "string", description: "Budget amount, a non-negative number (required for a paid publish)." },
536
536
  "budget-scope": { type: "string", description: "Budget scope (required for a paid publish): DAILY|TOTAL." }
537
537
  },
538
538
  async run({ args }) {
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  GLOBAL_FLAGS,
7
7
  writeProfile
8
- } from "./chunk-TMU3CSPR.js";
8
+ } from "./chunk-DW2HCRXJ.js";
9
9
 
10
10
  // src/commands/login.ts
11
11
  import { defineCommand } from "citty";
@@ -66,7 +66,7 @@ var loginCommand = defineCommand({
66
66
  apiKey = await promptMasked("Enter your API key: ");
67
67
  } else {
68
68
  process.stderr.write(
69
- "error: no API key \u2014 pass --api-key or run interactively on a TTY.\n"
69
+ "error: no API key, pass --api-key or run interactively on a TTY.\n"
70
70
  );
71
71
  process.exit(2);
72
72
  return;
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ guardBareMessageForm,
3
4
  messageCommand,
4
5
  runMessageAttachment,
5
6
  runMessageDelete,
@@ -12,15 +13,17 @@ import {
12
13
  runMessageSend,
13
14
  sentAsNotice,
14
15
  willSendAsNotice
15
- } from "./chunk-KVV6LZ7E.js";
16
+ } from "./chunk-IGCQNDIG.js";
17
+ import "./chunk-HOQ7EUHJ.js";
16
18
  import "./chunk-U7Y4EXHT.js";
17
19
  import "./chunk-BGZW6B7G.js";
18
20
  import "./chunk-UWO2D4HW.js";
19
21
  import "./chunk-DMQZEPQE.js";
20
22
  import "./chunk-R3VLWLVV.js";
21
- import "./chunk-M33MI53G.js";
22
- import "./chunk-TMU3CSPR.js";
23
+ import "./chunk-HDQUEFD2.js";
24
+ import "./chunk-DW2HCRXJ.js";
23
25
  export {
26
+ guardBareMessageForm,
24
27
  messageCommand,
25
28
  runMessageAttachment,
26
29
  runMessageDelete,
@@ -0,0 +1,219 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ pageDelayFromFlags,
4
+ streamAll
5
+ } from "./chunk-EEMJDJ4W.js";
6
+ import {
7
+ buildPreviewOutput
8
+ } from "./chunk-R3VLWLVV.js";
9
+ import {
10
+ createClient,
11
+ renderError,
12
+ renderSuccess,
13
+ renderUnexpectedError,
14
+ resolveEffectiveConfig
15
+ } from "./chunk-HDQUEFD2.js";
16
+ import {
17
+ GLOBAL_FLAGS,
18
+ WRITE_SINGLE_FLAGS
19
+ } from "./chunk-DW2HCRXJ.js";
20
+
21
+ // src/commands/notification.ts
22
+ import { defineCommand } from "citty";
23
+ function buildOutputStreams() {
24
+ return {
25
+ stdout: { write: (s) => process.stdout.write(s) },
26
+ stderr: { write: (s) => process.stderr.write(s) }
27
+ };
28
+ }
29
+ function requireAccount(account, out) {
30
+ if (!account) {
31
+ out.stderr.write("error: --account is required for this command. Set it via --account, CURVIATE_ACCOUNT, or `curviate config set-account`.\n");
32
+ process.exit(2);
33
+ }
34
+ return account;
35
+ }
36
+ function rejectPreviewOnRead(preview, out) {
37
+ if (preview) {
38
+ out.stderr.write("error: --preview is only valid on write commands (mutations). Reads just run.\n");
39
+ process.exit(2);
40
+ }
41
+ }
42
+ function resolveOutputOpts(flags) {
43
+ return {
44
+ json: (flags.json ?? false) || !process.stdout.isTTY,
45
+ isTTY: process.stdout.isTTY ?? false,
46
+ fields: flags.fields,
47
+ verbose: flags.verbose ?? false
48
+ };
49
+ }
50
+ async function handleSdkError(err, outOpts, out) {
51
+ const { CurviateError } = await import("@curviate/sdk");
52
+ if (err instanceof CurviateError) {
53
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
54
+ renderError(err, outOpts, out);
55
+ process.exit(getExitCode(err.code));
56
+ }
57
+ renderUnexpectedError(err, out);
58
+ process.exit(1);
59
+ }
60
+ async function runNotificationList(client, flags, out) {
61
+ rejectPreviewOnRead(flags.preview, out);
62
+ const accountId = requireAccount(flags.account, out);
63
+ const ns = client.account(accountId);
64
+ const outOpts = resolveOutputOpts(flags);
65
+ const all = flags.all ?? false;
66
+ const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
67
+ const params = {};
68
+ if (flags.filter) params["filter"] = flags.filter;
69
+ if (flags.limit) params["limit"] = parseInt(flags.limit, 10);
70
+ if (flags.cursor) params["cursor"] = flags.cursor;
71
+ try {
72
+ if (all) {
73
+ const fn = (p) => ns.notifications.list(p);
74
+ for await (const item of streamAll(fn, params, {
75
+ maxPages,
76
+ out,
77
+ pageDelayMs: pageDelayFromFlags(flags)
78
+ })) {
79
+ out.stdout.write(JSON.stringify(item) + "\n");
80
+ }
81
+ } else {
82
+ const result = await ns.notifications.list(params);
83
+ renderSuccess(result, outOpts, out);
84
+ }
85
+ } catch (err) {
86
+ await handleSdkError(err, outOpts, out);
87
+ }
88
+ }
89
+ async function runNotificationDelete(client, flags, out) {
90
+ const accountId = requireAccount(flags.account, out);
91
+ const cardUrn = flags.cardUrn ?? "";
92
+ if (flags.preview) {
93
+ const preview = buildPreviewOutput({ method: "notifications.delete", args: { card_urn: cardUrn }, body: {}, account: accountId });
94
+ out.stdout.write(JSON.stringify(preview) + "\n");
95
+ return;
96
+ }
97
+ const ns = client.account(accountId);
98
+ const outOpts = resolveOutputOpts(flags);
99
+ try {
100
+ const result = await ns.notifications.delete(cardUrn);
101
+ renderSuccess(result, outOpts, out);
102
+ } catch (err) {
103
+ await handleSdkError(err, outOpts, out);
104
+ }
105
+ }
106
+ async function runNotificationShowLess(client, flags, out) {
107
+ const accountId = requireAccount(flags.account, out);
108
+ const cardUrn = flags.cardUrn ?? "";
109
+ if (flags.preview) {
110
+ const preview = buildPreviewOutput({ method: "notifications.showLess", args: { card_urn: cardUrn }, body: {}, account: accountId });
111
+ out.stdout.write(JSON.stringify(preview) + "\n");
112
+ return;
113
+ }
114
+ const ns = client.account(accountId);
115
+ const outOpts = resolveOutputOpts(flags);
116
+ try {
117
+ const result = await ns.notifications.showLess(cardUrn);
118
+ renderSuccess(result, outOpts, out);
119
+ } catch (err) {
120
+ await handleSdkError(err, outOpts, out);
121
+ }
122
+ }
123
+ var notificationListCommand = defineCommand({
124
+ meta: { name: "list", description: "List the connected account's notification cards, newest first, plus the unread badge and a poll watermark." },
125
+ args: {
126
+ ...GLOBAL_FLAGS,
127
+ filter: {
128
+ type: "string",
129
+ description: "Which notification stream to read (default all): all | jobs | mentions | my_posts | my_posts_comments | my_posts_reactions | my_posts_reposts."
130
+ }
131
+ },
132
+ async run({ args }) {
133
+ const flags = args;
134
+ const cfg = await resolveEffectiveConfig({
135
+ apiKey: flags["api-key"],
136
+ baseUrl: flags["base-url"],
137
+ timeout: flags.timeout,
138
+ account: flags.account,
139
+ profile: flags.profile
140
+ });
141
+ if (!cfg.apiKey) {
142
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
143
+ process.exit(3);
144
+ }
145
+ const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
146
+ const out = buildOutputStreams();
147
+ await runNotificationList(client, { ...flags, account: flags.account ?? cfg.account }, out);
148
+ }
149
+ });
150
+ var notificationDeleteCommand = defineCommand({
151
+ meta: { name: "delete", description: "Delete one of your notification cards by its card urn. Self-action, idempotent, cannot be undone." },
152
+ args: {
153
+ ...WRITE_SINGLE_FLAGS,
154
+ cardUrn: { type: "positional", description: "The card_urn field of a `notification list` item (not object_urn)." }
155
+ },
156
+ async run({ args }) {
157
+ const flags = args;
158
+ const cfg = await resolveEffectiveConfig({
159
+ apiKey: flags["api-key"],
160
+ baseUrl: flags["base-url"],
161
+ timeout: flags.timeout,
162
+ account: flags.account,
163
+ profile: flags.profile
164
+ });
165
+ if (!cfg.apiKey) {
166
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
167
+ process.exit(3);
168
+ }
169
+ const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
170
+ const out = buildOutputStreams();
171
+ await runNotificationDelete(client, { ...flags, account: flags.account ?? cfg.account }, out);
172
+ }
173
+ });
174
+ var notificationShowLessCommand = defineCommand({
175
+ meta: {
176
+ name: "show-less",
177
+ description: "Apply 'show less like this' to the source of one of your notification cards. For network-activity cards this removes the card, same as delete. Self-action, idempotent, cannot be undone."
178
+ },
179
+ args: {
180
+ ...WRITE_SINGLE_FLAGS,
181
+ cardUrn: { type: "positional", description: "The card_urn field of a `notification list` item (not object_urn)." }
182
+ },
183
+ async run({ args }) {
184
+ const flags = args;
185
+ const cfg = await resolveEffectiveConfig({
186
+ apiKey: flags["api-key"],
187
+ baseUrl: flags["base-url"],
188
+ timeout: flags.timeout,
189
+ account: flags.account,
190
+ profile: flags.profile
191
+ });
192
+ if (!cfg.apiKey) {
193
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
194
+ process.exit(3);
195
+ }
196
+ const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
197
+ const out = buildOutputStreams();
198
+ await runNotificationShowLess(client, { ...flags, account: flags.account ?? cfg.account }, out);
199
+ }
200
+ });
201
+ var notificationCommand = defineCommand({
202
+ meta: { name: "notification", description: "Read and act on LinkedIn notification cards." },
203
+ subCommands: {
204
+ list: notificationListCommand,
205
+ delete: notificationDeleteCommand,
206
+ "show-less": notificationShowLessCommand
207
+ },
208
+ async run() {
209
+ process.stderr.write(
210
+ "Usage: curviate notification <subcommand>\n list [--filter <f>]\n delete <card_urn>\n show-less <card_urn>\n"
211
+ );
212
+ }
213
+ });
214
+ export {
215
+ notificationCommand,
216
+ runNotificationDelete,
217
+ runNotificationList,
218
+ runNotificationShowLess
219
+ };
@@ -24,12 +24,12 @@ import {
24
24
  renderSuccess,
25
25
  renderUnexpectedError,
26
26
  resolveEffectiveConfig
27
- } from "./chunk-M33MI53G.js";
27
+ } from "./chunk-HDQUEFD2.js";
28
28
  import {
29
29
  GLOBAL_FLAGS,
30
30
  WRITE_FLAGS,
31
31
  WRITE_SINGLE_FLAGS
32
- } from "./chunk-TMU3CSPR.js";
32
+ } from "./chunk-DW2HCRXJ.js";
33
33
 
34
34
  // src/commands/post.ts
35
35
  import { defineCommand } from "citty";
@@ -208,6 +208,66 @@ async function runPostReactions(client, flags, out) {
208
208
  await handleSdkError(err, outOpts, out);
209
209
  }
210
210
  }
211
+ async function runPostSaved(client, flags, out) {
212
+ rejectPreviewOnRead(flags.preview, out);
213
+ const accountId = requireAccount(flags.account, out);
214
+ const ns = client.account(accountId);
215
+ const outOpts = resolveOutputOpts(flags);
216
+ const all = flags.all ?? false;
217
+ const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
218
+ const params = buildPaginationParams(flags);
219
+ try {
220
+ if (all) {
221
+ const fn = (p) => ns.posts.listSaved(p);
222
+ for await (const item of streamAll(fn, params, {
223
+ maxPages,
224
+ out,
225
+ pageDelayMs: pageDelayFromFlags(flags)
226
+ })) {
227
+ out.stdout.write(JSON.stringify(item) + "\n");
228
+ }
229
+ } else {
230
+ const result = await ns.posts.listSaved(params);
231
+ renderSuccess(result, outOpts, out);
232
+ }
233
+ } catch (err) {
234
+ await handleSdkError(err, outOpts, out);
235
+ }
236
+ }
237
+ async function runPostSave(client, flags, out) {
238
+ const accountId = requireAccount(flags.account, out);
239
+ const postId = flags.postId ?? "";
240
+ if (flags.preview) {
241
+ const preview = buildPreviewOutput({ method: "posts.save", args: { post_id: postId }, body: {}, account: accountId });
242
+ out.stdout.write(JSON.stringify(preview) + "\n");
243
+ return;
244
+ }
245
+ const ns = client.account(accountId);
246
+ const outOpts = resolveOutputOpts(flags);
247
+ try {
248
+ const result = await ns.posts.save(postId);
249
+ renderSuccess(result, outOpts, out);
250
+ } catch (err) {
251
+ await handleSdkError(err, outOpts, out);
252
+ }
253
+ }
254
+ async function runPostUnsave(client, flags, out) {
255
+ const accountId = requireAccount(flags.account, out);
256
+ const postId = flags.postId ?? "";
257
+ if (flags.preview) {
258
+ const preview = buildPreviewOutput({ method: "posts.unsave", args: { post_id: postId }, body: {}, account: accountId });
259
+ out.stdout.write(JSON.stringify(preview) + "\n");
260
+ return;
261
+ }
262
+ const ns = client.account(accountId);
263
+ const outOpts = resolveOutputOpts(flags);
264
+ try {
265
+ const result = await ns.posts.unsave(postId);
266
+ renderSuccess(result, outOpts, out);
267
+ } catch (err) {
268
+ await handleSdkError(err, outOpts, out);
269
+ }
270
+ }
211
271
  async function runPostDelete(client, flags, out) {
212
272
  const accountId = requireAccount(flags.account, out);
213
273
  const postId = flags.postId ?? "";
@@ -339,7 +399,7 @@ var postGetCommand = defineCommand({
339
399
  profile: flags.profile
340
400
  });
341
401
  if (!cfg.apiKey) {
342
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
402
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
343
403
  process.exit(3);
344
404
  }
345
405
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
@@ -368,7 +428,7 @@ var postCreateCommand = defineCommand({
368
428
  profile: flags.profile
369
429
  });
370
430
  if (!cfg.apiKey) {
371
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
431
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
372
432
  process.exit(3);
373
433
  }
374
434
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
@@ -397,7 +457,7 @@ var postReactCommand = defineCommand({
397
457
  },
398
458
  "as-organization": {
399
459
  type: "string",
400
- description: "React on behalf of an organization/company page you administer \u2014 pass that page's numeric id or URN."
460
+ description: "React on behalf of an organization/company page you administer. Pass that page's numeric id or URN."
401
461
  }
402
462
  },
403
463
  async run({ args }) {
@@ -410,7 +470,7 @@ var postReactCommand = defineCommand({
410
470
  profile: flags.profile
411
471
  });
412
472
  if (!cfg.apiKey) {
413
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
473
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
414
474
  process.exit(3);
415
475
  }
416
476
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
@@ -437,7 +497,7 @@ var postReactionsCommand = defineCommand({
437
497
  profile: flags.profile
438
498
  });
439
499
  if (!cfg.apiKey) {
440
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
500
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
441
501
  process.exit(3);
442
502
  }
443
503
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
@@ -454,7 +514,7 @@ async function withClient(flags, fn) {
454
514
  profile: flags.profile
455
515
  });
456
516
  if (!cfg.apiKey) {
457
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
517
+ process.stderr.write("error: no API key, run `curviate login` or pass --api-key.\n");
458
518
  process.exit(3);
459
519
  }
460
520
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
@@ -482,6 +542,33 @@ var postUnreactCommand = defineCommand({
482
542
  await withClient(args, runPostUnreact);
483
543
  }
484
544
  });
545
+ var postSavedCommand = defineCommand({
546
+ meta: { name: "saved", description: "List your own saved posts (a private bookmark list, newest-saved-first). Each item is a preview (snippet capped at 140 chars)." },
547
+ args: { ...GLOBAL_FLAGS },
548
+ async run({ args }) {
549
+ await withClient(args, runPostSaved);
550
+ }
551
+ });
552
+ var postSaveCommand = defineCommand({
553
+ meta: { name: "save", description: "Save a post to your private bookmark list. Never notifies the author, never visible to third parties. Idempotent." },
554
+ args: {
555
+ ...WRITE_SINGLE_FLAGS,
556
+ postId: { type: "positional", description: "Post id (urn:li:activity:N or a bare numeric id)." }
557
+ },
558
+ async run({ args }) {
559
+ await withClient(args, runPostSave);
560
+ }
561
+ });
562
+ var postUnsaveCommand = defineCommand({
563
+ meta: { name: "unsave", description: "Remove a post from your saved-posts bookmark list. Idempotent." },
564
+ args: {
565
+ ...WRITE_SINGLE_FLAGS,
566
+ postId: { type: "positional", description: "Post id (urn:li:activity:N or a bare numeric id)." }
567
+ },
568
+ async run({ args }) {
569
+ await withClient(args, runPostUnsave);
570
+ }
571
+ });
485
572
  var postUserPostsCommand = defineCommand({
486
573
  meta: { name: "user-posts", description: "List a member's own posts (accepts 'me'). A very recent create/delete may take a few minutes to appear or clear here (LinkedIn-side indexing); `post get <post_id>` reflects it immediately." },
487
574
  args: {
@@ -511,12 +598,15 @@ var postCommand = defineCommand({
511
598
  reactions: postReactionsCommand,
512
599
  delete: postDeleteCommand,
513
600
  unreact: postUnreactCommand,
601
+ saved: postSavedCommand,
602
+ save: postSaveCommand,
603
+ unsave: postUnsaveCommand,
514
604
  "user-posts": postUserPostsCommand,
515
605
  "user-reactions": postUserReactionsCommand
516
606
  },
517
607
  async run() {
518
608
  process.stderr.write(
519
- 'Usage: curviate post <subcommand>\n get <post_id>\n create "<text>" [--attach <file>\u2026]\n react <post_id> <reaction> [--as-organization <org_id>]\n reactions <post_id>\n delete <post_id>\n unreact <post_id> <reaction>\n user-posts <user_id>\n user-reactions <user_id>\n\nComment operations moved to the `comment` command group.\n'
609
+ 'Usage: curviate post <subcommand>\n get <post_id>\n create "<text>" [--attach <file>\u2026]\n react <post_id> <reaction> [--as-organization <org_id>]\n reactions <post_id>\n delete <post_id>\n unreact <post_id> <reaction>\n saved\n save <post_id>\n unsave <post_id>\n user-posts <user_id>\n user-reactions <user_id>\n\nComment operations moved to the `comment` command group.\n'
520
610
  );
521
611
  }
522
612
  });
@@ -527,7 +617,10 @@ export {
527
617
  runPostGet,
528
618
  runPostReact,
529
619
  runPostReactions,
620
+ runPostSave,
621
+ runPostSaved,
530
622
  runPostUnreact,
623
+ runPostUnsave,
531
624
  runPostUserPosts,
532
625
  runPostUserReactions
533
626
  };