@curviate/cli 0.14.0 → 0.15.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.
@@ -0,0 +1,550 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ resolveTextOrStdin
4
+ } from "./chunk-U7Y4EXHT.js";
5
+ import {
6
+ resolveMemberOrMeProviderId
7
+ } from "./chunk-QJZ3LWOX.js";
8
+ import {
9
+ AttachError,
10
+ describeAttachment,
11
+ readAttachment,
12
+ toAttachmentPayload
13
+ } from "./chunk-BGZW6B7G.js";
14
+ import {
15
+ buildPreviewOutput
16
+ } from "./chunk-R3VLWLVV.js";
17
+ import "./chunk-DMQZEPQE.js";
18
+ import {
19
+ streamAll
20
+ } from "./chunk-DNTRQZBT.js";
21
+ import {
22
+ createClient,
23
+ renderError,
24
+ renderSuccess,
25
+ renderUnexpectedError,
26
+ resolveEffectiveConfig
27
+ } from "./chunk-JXF47TRY.js";
28
+ import {
29
+ GLOBAL_FLAGS,
30
+ WRITE_SINGLE_FLAGS
31
+ } from "./chunk-4JHGVY7R.js";
32
+
33
+ // src/commands/comment.ts
34
+ import { defineCommand } from "citty";
35
+ var REACTIONS = ["like", "celebrate", "support", "love", "insightful", "funny"];
36
+ function buildOutputStreams() {
37
+ return {
38
+ stdout: { write: (s) => process.stdout.write(s) },
39
+ stderr: { write: (s) => process.stderr.write(s) }
40
+ };
41
+ }
42
+ function requireAccount(account, out) {
43
+ if (!account) {
44
+ out.stderr.write("error: --account is required for this command. Set it via --account, CURVIATE_ACCOUNT, or `curviate config set-account`.\n");
45
+ process.exit(2);
46
+ }
47
+ return account;
48
+ }
49
+ function rejectPreviewOnRead(preview, out) {
50
+ if (preview) {
51
+ out.stderr.write("error: --preview is only valid on write commands (mutations). Reads just run.\n");
52
+ process.exit(2);
53
+ }
54
+ }
55
+ function resolveOutputOpts(flags) {
56
+ return {
57
+ json: (flags.json ?? false) || !process.stdout.isTTY,
58
+ isTTY: process.stdout.isTTY ?? false,
59
+ fields: flags.fields,
60
+ verbose: flags.verbose ?? false
61
+ };
62
+ }
63
+ function buildListQuery(flags) {
64
+ const params = {};
65
+ if (flags.limit) params.limit = parseInt(flags.limit, 10);
66
+ if (flags.cursor) params.cursor = flags.cursor;
67
+ return params;
68
+ }
69
+ async function handleSdkError(err, outOpts, out) {
70
+ const { CurviateError } = await import("@curviate/sdk");
71
+ if (err instanceof CurviateError) {
72
+ const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
73
+ renderError(err, outOpts, out);
74
+ process.exit(getExitCode(err.code));
75
+ }
76
+ renderUnexpectedError(err, out);
77
+ process.exit(1);
78
+ }
79
+ function normalizeAttachPaths(attach) {
80
+ if (!attach) return [];
81
+ return Array.isArray(attach) ? attach : [attach];
82
+ }
83
+ function assertReaction(reaction, out) {
84
+ if (!REACTIONS.includes(reaction)) {
85
+ out.stderr.write(
86
+ `error: reaction must be one of: ${REACTIONS.join(", ")}. Got "${reaction}".
87
+ `
88
+ );
89
+ process.exit(2);
90
+ }
91
+ }
92
+ async function runCommentList(client, flags, out) {
93
+ rejectPreviewOnRead(flags.preview, out);
94
+ const accountId = requireAccount(flags.account, out);
95
+ const postId = flags.postId ?? "";
96
+ const ns = client.account(accountId);
97
+ const outOpts = resolveOutputOpts(flags);
98
+ const all = flags.all ?? false;
99
+ const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
100
+ const params = buildListQuery(flags);
101
+ try {
102
+ if (all) {
103
+ const fn = (p) => ns.posts.listComments(postId, p);
104
+ for await (const item of streamAll(fn, params, {
105
+ maxPages,
106
+ out
107
+ })) {
108
+ out.stdout.write(JSON.stringify(item) + "\n");
109
+ }
110
+ } else {
111
+ const result = await ns.posts.listComments(postId, params);
112
+ renderSuccess(result, outOpts, out);
113
+ }
114
+ } catch (err) {
115
+ await handleSdkError(err, outOpts, out);
116
+ }
117
+ }
118
+ async function runCommentReplies(client, flags, out) {
119
+ rejectPreviewOnRead(flags.preview, out);
120
+ const accountId = requireAccount(flags.account, out);
121
+ const postId = flags.postId ?? "";
122
+ const commentId = flags.commentId ?? "";
123
+ const ns = client.account(accountId);
124
+ const outOpts = resolveOutputOpts(flags);
125
+ const all = flags.all ?? false;
126
+ const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
127
+ const params = buildListQuery(flags);
128
+ try {
129
+ if (all) {
130
+ const fn = (p) => ns.comments.listReplies(postId, commentId, p);
131
+ for await (const item of streamAll(fn, params, {
132
+ maxPages,
133
+ out
134
+ })) {
135
+ out.stdout.write(JSON.stringify(item) + "\n");
136
+ }
137
+ } else {
138
+ const result = await ns.comments.listReplies(postId, commentId, params);
139
+ renderSuccess(result, outOpts, out);
140
+ }
141
+ } catch (err) {
142
+ await handleSdkError(err, outOpts, out);
143
+ }
144
+ }
145
+ async function runCommentReactions(client, flags, out) {
146
+ rejectPreviewOnRead(flags.preview, out);
147
+ const accountId = requireAccount(flags.account, out);
148
+ const postId = flags.postId ?? "";
149
+ const commentId = flags.commentId ?? "";
150
+ const ns = client.account(accountId);
151
+ const outOpts = resolveOutputOpts(flags);
152
+ const all = flags.all ?? false;
153
+ const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
154
+ const params = buildListQuery(flags);
155
+ try {
156
+ if (all) {
157
+ const fn = (p) => ns.comments.listReactions(postId, commentId, p);
158
+ for await (const item of streamAll(fn, params, {
159
+ maxPages,
160
+ out
161
+ })) {
162
+ out.stdout.write(JSON.stringify(item) + "\n");
163
+ }
164
+ } else {
165
+ const result = await ns.comments.listReactions(postId, commentId, params);
166
+ renderSuccess(result, outOpts, out);
167
+ }
168
+ } catch (err) {
169
+ await handleSdkError(err, outOpts, out);
170
+ }
171
+ }
172
+ async function runCommentUser(client, flags, out) {
173
+ rejectPreviewOnRead(flags.preview, out);
174
+ const accountId = requireAccount(flags.account, out);
175
+ const ns = client.account(accountId);
176
+ const outOpts = resolveOutputOpts(flags);
177
+ let userId;
178
+ try {
179
+ userId = await resolveMemberOrMeProviderId(ns, flags.userId ?? "");
180
+ } catch (err) {
181
+ await handleSdkError(err, outOpts, out);
182
+ return;
183
+ }
184
+ const all = flags.all ?? false;
185
+ const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
186
+ const params = buildListQuery(flags);
187
+ try {
188
+ if (all) {
189
+ const fn = (p) => ns.comments.listUserComments(userId, p);
190
+ for await (const item of streamAll(fn, params, {
191
+ maxPages,
192
+ out
193
+ })) {
194
+ out.stdout.write(JSON.stringify(item) + "\n");
195
+ }
196
+ } else {
197
+ const result = await ns.comments.listUserComments(userId, params);
198
+ renderSuccess(result, outOpts, out);
199
+ }
200
+ } catch (err) {
201
+ await handleSdkError(err, outOpts, out);
202
+ }
203
+ }
204
+ async function runCommentAdd(client, flags, out, readStdin) {
205
+ const accountId = requireAccount(flags.account, out);
206
+ const postId = flags.postId ?? "";
207
+ const attachPaths = normalizeAttachPaths(flags.attach);
208
+ let attachBuffers = [];
209
+ try {
210
+ attachBuffers = await Promise.all(attachPaths.map((p) => readAttachment(p)));
211
+ } catch (err) {
212
+ if (err instanceof AttachError) {
213
+ out.stderr.write(`error: ${err.message}
214
+ `);
215
+ process.exit(err.exitCode);
216
+ }
217
+ throw err;
218
+ }
219
+ const text = await resolveTextOrStdin(flags.text ?? "", out, readStdin);
220
+ const attachmentPayloads = attachBuffers.map((buf, i) => toAttachmentPayload(attachPaths[i], buf));
221
+ const body = {
222
+ text,
223
+ ...attachmentPayloads.length > 0 ? { attachments: attachmentPayloads } : {}
224
+ };
225
+ if (flags.preview) {
226
+ const preview = buildPreviewOutput({
227
+ method: "comments.create",
228
+ args: { post_id: postId },
229
+ body: { text },
230
+ account: accountId,
231
+ attachments: attachBuffers.map((buf, i) => ({ name: describeAttachment(attachPaths[i], buf), buffer: buf }))
232
+ });
233
+ out.stdout.write(JSON.stringify(preview) + "\n");
234
+ return;
235
+ }
236
+ const ns = client.account(accountId);
237
+ const outOpts = resolveOutputOpts(flags);
238
+ try {
239
+ const result = await ns.comments.create(postId, body);
240
+ renderSuccess(result, outOpts, out);
241
+ } catch (err) {
242
+ await handleSdkError(err, outOpts, out);
243
+ }
244
+ }
245
+ async function runCommentReply(client, flags, out, readStdin) {
246
+ const accountId = requireAccount(flags.account, out);
247
+ const postId = flags.postId ?? "";
248
+ const commentId = flags.commentId ?? "";
249
+ const attachPaths = normalizeAttachPaths(flags.attach);
250
+ let attachBuffers = [];
251
+ try {
252
+ attachBuffers = await Promise.all(attachPaths.map((p) => readAttachment(p)));
253
+ } catch (err) {
254
+ if (err instanceof AttachError) {
255
+ out.stderr.write(`error: ${err.message}
256
+ `);
257
+ process.exit(err.exitCode);
258
+ }
259
+ throw err;
260
+ }
261
+ const text = await resolveTextOrStdin(flags.text ?? "", out, readStdin);
262
+ const attachmentPayloads = attachBuffers.map((buf, i) => toAttachmentPayload(attachPaths[i], buf));
263
+ const body = {
264
+ text,
265
+ ...attachmentPayloads.length > 0 ? { attachments: attachmentPayloads } : {}
266
+ };
267
+ if (flags.preview) {
268
+ const preview = buildPreviewOutput({
269
+ method: "comments.reply",
270
+ args: { post_id: postId, comment_id: commentId },
271
+ body: { text },
272
+ account: accountId,
273
+ attachments: attachBuffers.map((buf, i) => ({ name: describeAttachment(attachPaths[i], buf), buffer: buf }))
274
+ });
275
+ out.stdout.write(JSON.stringify(preview) + "\n");
276
+ return;
277
+ }
278
+ const ns = client.account(accountId);
279
+ const outOpts = resolveOutputOpts(flags);
280
+ try {
281
+ const result = await ns.comments.reply(postId, commentId, body);
282
+ renderSuccess(result, outOpts, out);
283
+ } catch (err) {
284
+ await handleSdkError(err, outOpts, out);
285
+ }
286
+ }
287
+ async function runCommentEdit(client, flags, out, readStdin) {
288
+ const accountId = requireAccount(flags.account, out);
289
+ const postId = flags.postId ?? "";
290
+ const commentId = flags.commentId ?? "";
291
+ const text = await resolveTextOrStdin(flags.text ?? "", out, readStdin);
292
+ const body = { text };
293
+ if (flags.preview) {
294
+ const preview = buildPreviewOutput({
295
+ method: "comments.edit",
296
+ args: { post_id: postId, comment_id: commentId },
297
+ body,
298
+ account: accountId
299
+ });
300
+ out.stdout.write(JSON.stringify(preview) + "\n");
301
+ return;
302
+ }
303
+ const ns = client.account(accountId);
304
+ const outOpts = resolveOutputOpts(flags);
305
+ try {
306
+ const result = await ns.comments.edit(postId, commentId, body);
307
+ renderSuccess(result, outOpts, out);
308
+ } catch (err) {
309
+ await handleSdkError(err, outOpts, out);
310
+ }
311
+ }
312
+ async function runCommentDelete(client, flags, out) {
313
+ const accountId = requireAccount(flags.account, out);
314
+ const postId = flags.postId ?? "";
315
+ const commentId = flags.commentId ?? "";
316
+ if (flags.preview) {
317
+ const preview = buildPreviewOutput({
318
+ method: "comments.delete",
319
+ args: { post_id: postId, comment_id: commentId },
320
+ body: {},
321
+ account: accountId
322
+ });
323
+ out.stdout.write(JSON.stringify(preview) + "\n");
324
+ return;
325
+ }
326
+ const ns = client.account(accountId);
327
+ const outOpts = resolveOutputOpts(flags);
328
+ try {
329
+ const result = await ns.comments.delete(postId, commentId);
330
+ renderSuccess(result, outOpts, out);
331
+ } catch (err) {
332
+ await handleSdkError(err, outOpts, out);
333
+ }
334
+ }
335
+ async function runCommentReact(client, flags, out) {
336
+ const accountId = requireAccount(flags.account, out);
337
+ const postId = flags.postId ?? "";
338
+ const commentId = flags.commentId ?? "";
339
+ const reaction = flags.reaction ?? "";
340
+ assertReaction(reaction, out);
341
+ const body = { reaction };
342
+ if (flags.preview) {
343
+ const preview = buildPreviewOutput({
344
+ method: "comments.addReaction",
345
+ args: { post_id: postId, comment_id: commentId },
346
+ body,
347
+ account: accountId
348
+ });
349
+ out.stdout.write(JSON.stringify(preview) + "\n");
350
+ return;
351
+ }
352
+ const ns = client.account(accountId);
353
+ const outOpts = resolveOutputOpts(flags);
354
+ try {
355
+ const result = await ns.comments.addReaction(postId, commentId, body);
356
+ renderSuccess(result, outOpts, out);
357
+ } catch (err) {
358
+ await handleSdkError(err, outOpts, out);
359
+ }
360
+ }
361
+ async function runCommentUnreact(client, flags, out) {
362
+ const accountId = requireAccount(flags.account, out);
363
+ const postId = flags.postId ?? "";
364
+ const commentId = flags.commentId ?? "";
365
+ const reaction = flags.reaction ?? "";
366
+ assertReaction(reaction, out);
367
+ const body = { reaction };
368
+ if (flags.preview) {
369
+ const preview = buildPreviewOutput({
370
+ method: "comments.removeReaction",
371
+ args: { post_id: postId, comment_id: commentId },
372
+ body,
373
+ account: accountId
374
+ });
375
+ out.stdout.write(JSON.stringify(preview) + "\n");
376
+ return;
377
+ }
378
+ const ns = client.account(accountId);
379
+ const outOpts = resolveOutputOpts(flags);
380
+ try {
381
+ const result = await ns.comments.removeReaction(postId, commentId, body);
382
+ renderSuccess(result, outOpts, out);
383
+ } catch (err) {
384
+ await handleSdkError(err, outOpts, out);
385
+ }
386
+ }
387
+ async function withClient(flags, fn) {
388
+ const cfg = await resolveEffectiveConfig({
389
+ apiKey: flags["api-key"],
390
+ baseUrl: flags["base-url"],
391
+ timeout: flags.timeout,
392
+ account: flags.account,
393
+ profile: flags.profile
394
+ });
395
+ if (!cfg.apiKey) {
396
+ process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
397
+ process.exit(3);
398
+ }
399
+ const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
400
+ const out = buildOutputStreams();
401
+ await fn(client, { ...flags, account: flags.account ?? cfg.account }, out);
402
+ }
403
+ var commentListCommand = defineCommand({
404
+ meta: { name: "list", description: "List the comments on a post." },
405
+ args: {
406
+ ...GLOBAL_FLAGS,
407
+ postId: { type: "positional", description: "Post id (or share URN) to list comments for." }
408
+ },
409
+ async run({ args }) {
410
+ await withClient(args, runCommentList);
411
+ }
412
+ });
413
+ var commentRepliesCommand = defineCommand({
414
+ meta: { name: "replies", description: "List the replies to a comment." },
415
+ args: {
416
+ ...GLOBAL_FLAGS,
417
+ postId: { type: "positional", description: "Post id the comment belongs to." },
418
+ commentId: { type: "positional", description: "Comment id to list replies for." }
419
+ },
420
+ async run({ args }) {
421
+ await withClient(args, runCommentReplies);
422
+ }
423
+ });
424
+ var commentReactionsCommand = defineCommand({
425
+ meta: { name: "reactions", description: "List the reactions on a comment." },
426
+ args: {
427
+ ...GLOBAL_FLAGS,
428
+ postId: { type: "positional", description: "Post id the comment belongs to." },
429
+ commentId: { type: "positional", description: "Comment id to list reactions for." }
430
+ },
431
+ async run({ args }) {
432
+ await withClient(args, runCommentReactions);
433
+ }
434
+ });
435
+ var commentUserCommand = defineCommand({
436
+ meta: { name: "user", description: "List the comments authored by a user (accepts 'me')." },
437
+ args: {
438
+ ...GLOBAL_FLAGS,
439
+ userId: { type: "positional", description: "Member identifier (URL, slug, provider id, or 'me')." }
440
+ },
441
+ async run({ args }) {
442
+ await withClient(args, runCommentUser);
443
+ }
444
+ });
445
+ var commentAddCommand = defineCommand({
446
+ meta: { name: "add", description: "Publish a comment on a post." },
447
+ args: {
448
+ ...WRITE_SINGLE_FLAGS,
449
+ postId: { type: "positional", description: "Post id to comment on." },
450
+ text: { type: "positional", description: "Comment text. Pass - to read from stdin." },
451
+ attach: { type: "string", description: "Image file to attach (at most one)." }
452
+ },
453
+ async run({ args }) {
454
+ await withClient(args, (c, f, o) => runCommentAdd(c, f, o, void 0));
455
+ }
456
+ });
457
+ var commentReplyCommand = defineCommand({
458
+ meta: { name: "reply", description: "Reply to a comment." },
459
+ args: {
460
+ ...WRITE_SINGLE_FLAGS,
461
+ postId: { type: "positional", description: "Post id the comment belongs to." },
462
+ commentId: { type: "positional", description: "Comment id to reply to." },
463
+ text: { type: "positional", description: "Reply text. Pass - to read from stdin." },
464
+ attach: { type: "string", description: "Image file to attach (at most one)." }
465
+ },
466
+ async run({ args }) {
467
+ await withClient(args, (c, f, o) => runCommentReply(c, f, o, void 0));
468
+ }
469
+ });
470
+ var commentEditCommand = defineCommand({
471
+ meta: { name: "edit", description: "Edit your own comment." },
472
+ args: {
473
+ ...WRITE_SINGLE_FLAGS,
474
+ postId: { type: "positional", description: "Post id the comment belongs to." },
475
+ commentId: { type: "positional", description: "Comment id to edit." },
476
+ text: { type: "positional", description: "Updated comment text. Pass - to read from stdin." }
477
+ },
478
+ async run({ args }) {
479
+ await withClient(args, (c, f, o) => runCommentEdit(c, f, o, void 0));
480
+ }
481
+ });
482
+ var commentDeleteCommand = defineCommand({
483
+ meta: { name: "delete", description: "Delete your own comment." },
484
+ args: {
485
+ ...WRITE_SINGLE_FLAGS,
486
+ postId: { type: "positional", description: "Post id the comment belongs to." },
487
+ commentId: { type: "positional", description: "Comment id to delete." }
488
+ },
489
+ async run({ args }) {
490
+ await withClient(args, runCommentDelete);
491
+ }
492
+ });
493
+ var commentReactCommand = defineCommand({
494
+ meta: { name: "react", description: "React to a comment (like|celebrate|support|love|insightful|funny)." },
495
+ args: {
496
+ ...WRITE_SINGLE_FLAGS,
497
+ postId: { type: "positional", description: "Post id the comment belongs to." },
498
+ commentId: { type: "positional", description: "Comment id to react to." },
499
+ reaction: { type: "positional", description: "Reaction: like|celebrate|support|love|insightful|funny." }
500
+ },
501
+ async run({ args }) {
502
+ await withClient(args, runCommentReact);
503
+ }
504
+ });
505
+ var commentUnreactCommand = defineCommand({
506
+ meta: { name: "unreact", description: "Remove your reaction from a comment." },
507
+ args: {
508
+ ...WRITE_SINGLE_FLAGS,
509
+ postId: { type: "positional", description: "Post id the comment belongs to." },
510
+ commentId: { type: "positional", description: "Comment id to remove your reaction from." },
511
+ reaction: { type: "positional", description: "Reaction to remove: like|celebrate|support|love|insightful|funny." }
512
+ },
513
+ async run({ args }) {
514
+ await withClient(args, runCommentUnreact);
515
+ }
516
+ });
517
+ var commentCommand = defineCommand({
518
+ meta: { name: "comment", description: "Comment-thread operations (list, add, reply, edit, delete, react)." },
519
+ args: { ...GLOBAL_FLAGS },
520
+ subCommands: {
521
+ list: commentListCommand,
522
+ add: commentAddCommand,
523
+ reply: commentReplyCommand,
524
+ edit: commentEditCommand,
525
+ delete: commentDeleteCommand,
526
+ replies: commentRepliesCommand,
527
+ react: commentReactCommand,
528
+ reactions: commentReactionsCommand,
529
+ unreact: commentUnreactCommand,
530
+ user: commentUserCommand
531
+ },
532
+ async run() {
533
+ process.stderr.write(
534
+ "Usage: curviate comment list <post_id>\n curviate comment add <post_id> <text> [--attach <file>]\n curviate comment reply <post_id> <comment_id> <text>\n curviate comment edit <post_id> <comment_id> <text>\n curviate comment delete <post_id> <comment_id>\n curviate comment replies <post_id> <comment_id>\n curviate comment react <post_id> <comment_id> <reaction>\n curviate comment reactions <post_id> <comment_id>\n curviate comment unreact <post_id> <comment_id> <reaction>\n curviate comment user <user_id>\n"
535
+ );
536
+ }
537
+ });
538
+ export {
539
+ commentCommand,
540
+ runCommentAdd,
541
+ runCommentDelete,
542
+ runCommentEdit,
543
+ runCommentList,
544
+ runCommentReact,
545
+ runCommentReactions,
546
+ runCommentReplies,
547
+ runCommentReply,
548
+ runCommentUnreact,
549
+ runCommentUser
550
+ };