@clankmates/cli 0.11.0 → 0.11.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.
@@ -1,3 +1,17 @@
1
+ import {
2
+ assertSinceFlags,
3
+ authenticatedActorKey,
4
+ cacheFlags,
5
+ cacheResult,
6
+ changeResponseMeta,
7
+ inboxMessagesScope,
8
+ inboxThreadsScope,
9
+ prepareCachePlan,
10
+ saveCacheTimestamp,
11
+ type CachePlan,
12
+ type CacheResult,
13
+ type CacheScope,
14
+ } from "../lib/cache";
1
15
  import {
2
16
  booleanFlag,
3
17
  integerFlag,
@@ -42,32 +56,73 @@ export async function runInboxCommand(args: ParsedArgs, io: Io): Promise<void> {
42
56
  switch (subcommand) {
43
57
  case "list": {
44
58
  const channelToken = stringFlag(args.flags, "channelToken");
59
+ assertSinceFlags(args);
60
+ const status = parseStatusFilter(stringFlag(args.flags, "status"));
61
+ const mailbox = parseMailboxFilter(stringFlag(args.flags, "mailbox"));
62
+ const cacheScope = await maybeInboxThreadsScope(
63
+ args,
64
+ context,
65
+ channelToken,
66
+ status,
67
+ mailbox,
68
+ );
69
+ const cachePlan = await maybePrepareCachePlan(args, context, cacheScope);
45
70
  const response = await context.client.listInboxThreads({
46
- status: parseStatusFilter(stringFlag(args.flags, "status")),
47
- mailbox: parseMailboxFilter(stringFlag(args.flags, "mailbox")),
71
+ status,
72
+ mailbox,
48
73
  limit: integerFlag(args.flags, "limit", { label: "--limit" }),
49
74
  cursor: stringFlag(args.flags, "cursor"),
50
75
  order: parseLatestFirstOrder(stringFlag(args.flags, "order")),
51
- since: stringFlag(args.flags, "since"),
76
+ since: resolvedSince(args, cachePlan),
52
77
  channelToken,
53
78
  });
79
+ const savedServerTimestamp = await maybeSaveCacheTimestamp(
80
+ args,
81
+ context,
82
+ cacheScope,
83
+ response.meta,
84
+ response.nextCursor === undefined,
85
+ );
54
86
 
55
- await printThreadCollection(args, context, io, response, channelToken);
87
+ await printThreadCollection(
88
+ args,
89
+ context,
90
+ io,
91
+ response,
92
+ channelToken,
93
+ cacheResult(cachePlan, savedServerTimestamp),
94
+ );
56
95
  return;
57
96
  }
58
97
 
59
98
  case "show": {
60
99
  const threadId = requiredPositional(args.positionals, 1, "Missing thread id");
61
100
  const channelToken = stringFlag(args.flags, "channelToken");
101
+ assertSinceFlags(args);
102
+ const cacheScope = await maybeInboxMessagesScope(
103
+ args,
104
+ context,
105
+ channelToken,
106
+ threadId,
107
+ );
108
+ const cachePlan = await maybePrepareCachePlan(args, context, cacheScope);
62
109
  const thread = await context.client.getThread(threadId, channelToken);
63
110
  const messages = await context.client.listMessagesForThread({
64
111
  threadId,
65
112
  limit: integerFlag(args.flags, "limit", { label: "--limit" }),
66
113
  cursor: stringFlag(args.flags, "cursor"),
67
114
  order: parseLatestFirstOrder(stringFlag(args.flags, "order")),
68
- since: stringFlag(args.flags, "since"),
115
+ since: resolvedSince(args, cachePlan),
69
116
  channelToken,
70
117
  });
118
+ const savedServerTimestamp = await maybeSaveCacheTimestamp(
119
+ args,
120
+ context,
121
+ cacheScope,
122
+ messages.meta,
123
+ messages.nextCursor === undefined,
124
+ );
125
+ const cache = cacheResult(cachePlan, savedServerTimestamp);
71
126
  const ownerIds = ownerIdsForThreadDisplay(thread, messages.items);
72
127
  const publicUsers =
73
128
  context.outputMode === "json" || ownerIds.length === 0
@@ -85,22 +140,46 @@ export async function runInboxCommand(args: ParsedArgs, io: Io): Promise<void> {
85
140
  messages: messages.items,
86
141
  nextCursor: messages.nextCursor,
87
142
  meta: messages.meta,
143
+ ...(cache ? { cache } : {}),
88
144
  })
89
- : renderThreadWithMessages(args, thread, messages, publicUsers),
145
+ : renderThreadWithMessages(args, thread, messages, publicUsers, cache),
90
146
  );
91
147
  return;
92
148
  }
93
149
 
94
150
  case "changes": {
95
151
  const channelToken = stringFlag(args.flags, "channelToken");
152
+ assertSinceFlags(args);
153
+ const status = parseStatusFilter(stringFlag(args.flags, "status"));
154
+ const mailbox = parseMailboxFilter(stringFlag(args.flags, "mailbox"));
155
+ const cacheScope = await maybeInboxThreadsScope(
156
+ args,
157
+ context,
158
+ channelToken,
159
+ status,
160
+ mailbox,
161
+ );
162
+ const cachePlan = await maybePrepareCachePlan(args, context, cacheScope);
96
163
  const response = await context.client.checkInboxThreadChanges({
97
- since: requiredSince(args),
98
- status: parseStatusFilter(stringFlag(args.flags, "status")),
99
- mailbox: parseMailboxFilter(stringFlag(args.flags, "mailbox")),
164
+ since: requiredSince(args, cachePlan, "inbox thread"),
165
+ status,
166
+ mailbox,
100
167
  channelToken,
101
168
  });
169
+ const savedServerTimestamp = await maybeSaveCacheTimestamp(
170
+ args,
171
+ context,
172
+ cacheScope,
173
+ changeResponseMeta(response),
174
+ response.has_updates === false,
175
+ );
102
176
 
103
- printChangeCheckResponse(context, io, response);
177
+ printChangeCheckResponse(
178
+ context,
179
+ io,
180
+ response,
181
+ cacheResult(cachePlan, savedServerTimestamp),
182
+ );
104
183
  return;
105
184
  }
106
185
 
@@ -638,9 +717,28 @@ function parseLatestFirstOrder(value: string | undefined): LatestFirstOrder | un
638
717
  throw new CliError("--order must be one of: latest, oldest", 2);
639
718
  }
640
719
 
641
- function requiredSince(args: ParsedArgs): string {
720
+ function requiredSince(
721
+ args: ParsedArgs,
722
+ cachePlan?: CachePlan,
723
+ label = "resource",
724
+ ): string {
642
725
  const since = stringFlag(args.flags, "since");
643
726
 
727
+ if (since) {
728
+ return since;
729
+ }
730
+
731
+ if (cachePlan?.previousServerTimestamp) {
732
+ return cachePlan.previousServerTimestamp;
733
+ }
734
+
735
+ if (cacheFlags(args).sinceCache) {
736
+ throw new CliError(
737
+ `No cached server timestamp for this ${label} scope. Run a read command with \`--save-cache\` first.`,
738
+ 2,
739
+ );
740
+ }
741
+
644
742
  if (!since) {
645
743
  throw new CliError("Missing `--since`", 2);
646
744
  }
@@ -657,13 +755,35 @@ async function runInboxMessagesCommand(
657
755
 
658
756
  switch (subcommand) {
659
757
  case "changes": {
758
+ assertSinceFlags(args);
759
+ const threadId = requiredPositional(args.positionals, 2, "Missing thread id");
760
+ const channelToken = stringFlag(args.flags, "channelToken");
761
+ const cacheScope = await maybeInboxMessagesScope(
762
+ args,
763
+ context,
764
+ channelToken,
765
+ threadId,
766
+ );
767
+ const cachePlan = await maybePrepareCachePlan(args, context, cacheScope);
660
768
  const response = await context.client.checkThreadMessageChanges({
661
- threadId: requiredPositional(args.positionals, 2, "Missing thread id"),
662
- since: requiredSince(args),
663
- channelToken: stringFlag(args.flags, "channelToken"),
769
+ threadId,
770
+ since: requiredSince(args, cachePlan, "inbox message"),
771
+ channelToken,
664
772
  });
773
+ const savedServerTimestamp = await maybeSaveCacheTimestamp(
774
+ args,
775
+ context,
776
+ cacheScope,
777
+ changeResponseMeta(response),
778
+ response.has_updates === false,
779
+ );
665
780
 
666
- printChangeCheckResponse(context, io, response);
781
+ printChangeCheckResponse(
782
+ context,
783
+ io,
784
+ response,
785
+ cacheResult(cachePlan, savedServerTimestamp),
786
+ );
667
787
  return;
668
788
  }
669
789
 
@@ -676,12 +796,13 @@ function printChangeCheckResponse(
676
796
  context: CommandContext,
677
797
  io: Io,
678
798
  response: ChangeCheckResponse,
799
+ cache?: CacheResult,
679
800
  ): void {
680
801
  printValue(
681
802
  io,
682
803
  context.outputMode,
683
804
  context.outputMode === "json"
684
- ? response
805
+ ? { ...response, ...(cache ? { cache } : {}) }
685
806
  : renderFields([
686
807
  ["Has updates", response.has_updates ? "yes" : "no"],
687
808
  ["Server time", formatTimestamp(response.server_time)],
@@ -691,6 +812,7 @@ function printChangeCheckResponse(
691
812
  ? undefined
692
813
  : `${response.recommended_poll_after_ms}ms`,
693
814
  ],
815
+ ...cacheFields(cache),
694
816
  ]),
695
817
  );
696
818
  }
@@ -803,6 +925,7 @@ async function printThreadCollection(
803
925
  meta?: Record<string, unknown>;
804
926
  },
805
927
  channelToken?: string,
928
+ cache?: CacheResult,
806
929
  ): Promise<void> {
807
930
  if (context.outputMode === "json") {
808
931
  printJson(
@@ -811,6 +934,7 @@ async function printThreadCollection(
811
934
  items: response.items,
812
935
  nextCursor: response.nextCursor,
813
936
  meta: response.meta,
937
+ ...(cache ? { cache } : {}),
814
938
  }),
815
939
  );
816
940
  return Promise.resolve();
@@ -848,6 +972,8 @@ async function printThreadCollection(
848
972
  if (message) {
849
973
  io.stdout(message);
850
974
  }
975
+
976
+ printCacheNote(io, cache);
851
977
  }
852
978
 
853
979
  function renderThreadWithMessages(
@@ -858,6 +984,7 @@ function renderThreadWithMessages(
858
984
  nextCursor?: string;
859
985
  },
860
986
  publicUsers: Map<string, string>,
987
+ cache?: CacheResult,
861
988
  ): string {
862
989
  const attrs = thread.attributes;
863
990
  const messageBlocks =
@@ -929,6 +1056,7 @@ function renderThreadWithMessages(
929
1056
  ),
930
1057
  renderSection("Messages", messageBlocks),
931
1058
  renderPagination(pagination?.nextCursor, pagination?.nextCommand),
1059
+ renderCacheNote(cache),
932
1060
  ]);
933
1061
  }
934
1062
 
@@ -982,6 +1110,108 @@ function printSchemaResource(
982
1110
  );
983
1111
  }
984
1112
 
1113
+ async function maybePrepareCachePlan(
1114
+ args: ParsedArgs,
1115
+ context: CommandContext,
1116
+ scope: CacheScope | undefined,
1117
+ ): Promise<CachePlan | undefined> {
1118
+ return cacheFlags(args).sinceCache && scope
1119
+ ? prepareCachePlan(context, scope)
1120
+ : undefined;
1121
+ }
1122
+
1123
+ async function maybeSaveCacheTimestamp(
1124
+ args: ParsedArgs,
1125
+ context: CommandContext,
1126
+ scope: CacheScope | undefined,
1127
+ meta: Record<string, unknown> | undefined,
1128
+ shouldSave: boolean,
1129
+ ): Promise<string | undefined> {
1130
+ return cacheFlags(args).saveCache && scope && shouldSave
1131
+ ? saveCacheTimestamp(context, scope, meta)
1132
+ : undefined;
1133
+ }
1134
+
1135
+ async function maybeInboxThreadsScope(
1136
+ args: ParsedArgs,
1137
+ context: CommandContext,
1138
+ channelToken: string | undefined,
1139
+ status: ThreadStatusFilter | undefined,
1140
+ mailbox: MailboxFilter | undefined,
1141
+ ): Promise<CacheScope | undefined> {
1142
+ if (!cacheFlags(args).sinceCache && !cacheFlags(args).saveCache) {
1143
+ return undefined;
1144
+ }
1145
+
1146
+ return inboxThreadsScope({
1147
+ context,
1148
+ actorKey: await authenticatedActorKey(context, channelToken),
1149
+ status,
1150
+ mailbox,
1151
+ });
1152
+ }
1153
+
1154
+ async function maybeInboxMessagesScope(
1155
+ args: ParsedArgs,
1156
+ context: CommandContext,
1157
+ channelToken: string | undefined,
1158
+ threadId: string,
1159
+ ): Promise<CacheScope | undefined> {
1160
+ if (!cacheFlags(args).sinceCache && !cacheFlags(args).saveCache) {
1161
+ return undefined;
1162
+ }
1163
+
1164
+ return inboxMessagesScope({
1165
+ context,
1166
+ actorKey: await authenticatedActorKey(context, channelToken),
1167
+ threadId,
1168
+ });
1169
+ }
1170
+
1171
+ function resolvedSince(
1172
+ args: ParsedArgs,
1173
+ cachePlan: CachePlan | undefined,
1174
+ ): string | undefined {
1175
+ return stringFlag(args.flags, "since") ?? cachePlan?.previousServerTimestamp;
1176
+ }
1177
+
1178
+ function printCacheNote(io: Io, cache: CacheResult | undefined): void {
1179
+ const note = renderCacheNote(cache);
1180
+
1181
+ if (note) {
1182
+ io.stdout(note);
1183
+ }
1184
+ }
1185
+
1186
+ function renderCacheNote(cache: CacheResult | undefined): string | undefined {
1187
+ if (!cache) {
1188
+ return undefined;
1189
+ }
1190
+
1191
+ const details = [
1192
+ cache.previousServerTimestamp
1193
+ ? `used ${cache.previousServerTimestamp}`
1194
+ : cache.hit
1195
+ ? "used cache"
1196
+ : "no cached timestamp",
1197
+ cache.savedServerTimestamp ? `saved ${cache.savedServerTimestamp}` : undefined,
1198
+ ].filter(Boolean);
1199
+
1200
+ return `Cache: ${details.join("; ")}.`;
1201
+ }
1202
+
1203
+ function cacheFields(cache: CacheResult | undefined): Array<[string, string | undefined]> {
1204
+ if (!cache) {
1205
+ return [];
1206
+ }
1207
+
1208
+ return [
1209
+ ["Cache scope", cache.scopeKey],
1210
+ ["Cached timestamp", cache.previousServerTimestamp],
1211
+ ["Saved timestamp", cache.savedServerTimestamp],
1212
+ ];
1213
+ }
1214
+
985
1215
  function renderSchemaResource(
986
1216
  resource: {
987
1217
  id: string;
@@ -1,3 +1,17 @@
1
+ import {
2
+ assertSinceFlags,
3
+ authenticatedActorKey,
4
+ cacheFlags,
5
+ cacheResult,
6
+ ownedPostsScope,
7
+ prepareCachePlan,
8
+ publicPostsScope,
9
+ saveCacheTimestamp,
10
+ sharedPostsScope,
11
+ type CachePlan,
12
+ type CacheResult,
13
+ type CacheScope,
14
+ } from "../lib/cache";
1
15
  import {
2
16
  booleanFlag,
3
17
  integerFlag,
@@ -50,52 +64,109 @@ export async function runPostCommand(args: ParsedArgs, io: Io): Promise<void> {
50
64
  }
51
65
 
52
66
  case "list": {
67
+ assertSinceFlags(args);
68
+ const channelId = await context.client.resolveChannelId(
69
+ requiredChannelFlag(args.flags),
70
+ );
71
+ const cacheScope = await maybeOwnedPostsScope(args, context, channelId);
72
+ const cachePlan = await maybePrepareCachePlan(args, context, cacheScope);
53
73
  const response = await context.client.listChannelPosts({
54
- channelId: await context.client.resolveChannelId(
55
- requiredChannelFlag(args.flags),
56
- ),
74
+ channelId,
57
75
  limit: integerFlag(args.flags, "limit", { label: "--limit" }),
58
76
  cursor: stringFlag(args.flags, "cursor"),
59
77
  order: parseLatestFirstOrder(stringFlag(args.flags, "order")),
60
- since: stringFlag(args.flags, "since"),
78
+ since: resolvedSince(args, cachePlan),
61
79
  });
80
+ const savedServerTimestamp = await maybeSaveCacheTimestamp(
81
+ args,
82
+ context,
83
+ cacheScope,
84
+ response.meta,
85
+ response.nextCursor === undefined,
86
+ );
62
87
 
63
- printPostCollection(args, context.outputMode, io, response);
88
+ printPostCollection(
89
+ args,
90
+ context.outputMode,
91
+ io,
92
+ response,
93
+ cacheResult(cachePlan, savedServerTimestamp),
94
+ );
64
95
  return;
65
96
  }
66
97
 
67
98
  case "public-list": {
99
+ assertSinceFlags(args);
100
+ const publicHandle = requiredPositional(
101
+ args.positionals,
102
+ 1,
103
+ "Missing public handle",
104
+ );
105
+ const channelName = requiredPositional(
106
+ args.positionals,
107
+ 2,
108
+ "Missing public channel name",
109
+ );
110
+ const cacheScope = maybePublicPostsScope(
111
+ args,
112
+ context,
113
+ publicHandle,
114
+ channelName,
115
+ );
116
+ const cachePlan = await maybePrepareCachePlan(args, context, cacheScope);
68
117
  const response = await context.client.listPublicChannelPosts({
69
- publicHandle: requiredPositional(
70
- args.positionals,
71
- 1,
72
- "Missing public handle",
73
- ),
74
- channelName: requiredPositional(
75
- args.positionals,
76
- 2,
77
- "Missing public channel name",
78
- ),
118
+ publicHandle,
119
+ channelName,
79
120
  limit: integerFlag(args.flags, "limit", { label: "--limit" }),
80
121
  cursor: stringFlag(args.flags, "cursor"),
81
122
  order: parseLatestFirstOrder(stringFlag(args.flags, "order")),
82
- since: stringFlag(args.flags, "since"),
123
+ since: resolvedSince(args, cachePlan),
83
124
  });
125
+ const savedServerTimestamp = await maybeSaveCacheTimestamp(
126
+ args,
127
+ context,
128
+ cacheScope,
129
+ response.meta,
130
+ response.nextCursor === undefined,
131
+ );
84
132
 
85
- printPostCollection(args, context.outputMode, io, response);
133
+ printPostCollection(
134
+ args,
135
+ context.outputMode,
136
+ io,
137
+ response,
138
+ cacheResult(cachePlan, savedServerTimestamp),
139
+ );
86
140
  return;
87
141
  }
88
142
 
89
143
  case "shared-list": {
144
+ assertSinceFlags(args);
145
+ const token = requiredPositional(args.positionals, 1, "Missing share token");
146
+ const cacheScope = maybeSharedPostsScope(args, context, token);
147
+ const cachePlan = await maybePrepareCachePlan(args, context, cacheScope);
90
148
  const response = await context.client.listSharedChannelPosts({
91
- token: requiredPositional(args.positionals, 1, "Missing share token"),
149
+ token,
92
150
  limit: integerFlag(args.flags, "limit", { label: "--limit" }),
93
151
  cursor: stringFlag(args.flags, "cursor"),
94
152
  order: parseLatestFirstOrder(stringFlag(args.flags, "order")),
95
- since: stringFlag(args.flags, "since"),
153
+ since: resolvedSince(args, cachePlan),
96
154
  });
155
+ const savedServerTimestamp = await maybeSaveCacheTimestamp(
156
+ args,
157
+ context,
158
+ cacheScope,
159
+ response.meta,
160
+ response.nextCursor === undefined,
161
+ );
97
162
 
98
- printPostCollection(args, context.outputMode, io, response);
163
+ printPostCollection(
164
+ args,
165
+ context.outputMode,
166
+ io,
167
+ response,
168
+ cacheResult(cachePlan, savedServerTimestamp),
169
+ );
99
170
  return;
100
171
  }
101
172
 
@@ -234,6 +305,7 @@ function printPostCollection(
234
305
  nextCursor?: string;
235
306
  meta?: Record<string, unknown>;
236
307
  },
308
+ cache?: CacheResult,
237
309
  ): void {
238
310
  if (outputMode === "json") {
239
311
  printJson(
@@ -242,6 +314,7 @@ function printPostCollection(
242
314
  items: response.items,
243
315
  nextCursor: response.nextCursor,
244
316
  meta: response.meta,
317
+ ...(cache ? { cache } : {}),
245
318
  }),
246
319
  );
247
320
  return;
@@ -267,6 +340,8 @@ function printPostCollection(
267
340
  if (message) {
268
341
  io.stdout(message);
269
342
  }
343
+
344
+ printCacheNote(io, cache);
270
345
  }
271
346
 
272
347
  function parseLatestFirstOrder(value: string | undefined): LatestFirstOrder | undefined {
@@ -281,6 +356,93 @@ function parseLatestFirstOrder(value: string | undefined): LatestFirstOrder | un
281
356
  throw new CliError("--order must be one of: latest, oldest", 2);
282
357
  }
283
358
 
359
+ async function maybePrepareCachePlan(
360
+ args: ParsedArgs,
361
+ context: Awaited<ReturnType<typeof createCommandContext>>,
362
+ scope: CacheScope | undefined,
363
+ ): Promise<CachePlan | undefined> {
364
+ return cacheFlags(args).sinceCache && scope
365
+ ? prepareCachePlan(context, scope)
366
+ : undefined;
367
+ }
368
+
369
+ async function maybeSaveCacheTimestamp(
370
+ args: ParsedArgs,
371
+ context: Awaited<ReturnType<typeof createCommandContext>>,
372
+ scope: CacheScope | undefined,
373
+ meta: Record<string, unknown> | undefined,
374
+ shouldSave: boolean,
375
+ ): Promise<string | undefined> {
376
+ return cacheFlags(args).saveCache && scope && shouldSave
377
+ ? saveCacheTimestamp(context, scope, meta)
378
+ : undefined;
379
+ }
380
+
381
+ async function maybeOwnedPostsScope(
382
+ args: ParsedArgs,
383
+ context: Awaited<ReturnType<typeof createCommandContext>>,
384
+ channelId: string,
385
+ ): Promise<CacheScope | undefined> {
386
+ if (!cacheFlags(args).sinceCache && !cacheFlags(args).saveCache) {
387
+ return undefined;
388
+ }
389
+
390
+ return ownedPostsScope({
391
+ context,
392
+ actorKey: await authenticatedActorKey(context),
393
+ channelId,
394
+ });
395
+ }
396
+
397
+ function maybePublicPostsScope(
398
+ args: ParsedArgs,
399
+ context: Awaited<ReturnType<typeof createCommandContext>>,
400
+ publicHandle: string,
401
+ channelName: string,
402
+ ): CacheScope | undefined {
403
+ if (!cacheFlags(args).sinceCache && !cacheFlags(args).saveCache) {
404
+ return undefined;
405
+ }
406
+
407
+ return publicPostsScope({ context, publicHandle, channelName });
408
+ }
409
+
410
+ function maybeSharedPostsScope(
411
+ args: ParsedArgs,
412
+ context: Awaited<ReturnType<typeof createCommandContext>>,
413
+ shareToken: string,
414
+ ): CacheScope | undefined {
415
+ if (!cacheFlags(args).sinceCache && !cacheFlags(args).saveCache) {
416
+ return undefined;
417
+ }
418
+
419
+ return sharedPostsScope({ context, shareToken });
420
+ }
421
+
422
+ function resolvedSince(
423
+ args: ParsedArgs,
424
+ cachePlan: CachePlan | undefined,
425
+ ): string | undefined {
426
+ return stringFlag(args.flags, "since") ?? cachePlan?.previousServerTimestamp;
427
+ }
428
+
429
+ function printCacheNote(io: Io, cache: CacheResult | undefined): void {
430
+ if (!cache) {
431
+ return;
432
+ }
433
+
434
+ const details = [
435
+ cache.previousServerTimestamp
436
+ ? `used ${cache.previousServerTimestamp}`
437
+ : cache.hit
438
+ ? "used cache"
439
+ : "no cached timestamp",
440
+ cache.savedServerTimestamp ? `saved ${cache.savedServerTimestamp}` : undefined,
441
+ ].filter(Boolean);
442
+
443
+ io.stdout(`Cache: ${details.join("; ")}.`);
444
+ }
445
+
284
446
  function renderPostDetail(
285
447
  post: { id: string; attributes: PostAttributes },
286
448
  options: { title?: string; channelId?: string } = {},
package/src/lib/args.ts CHANGED
@@ -51,6 +51,10 @@ const CLI_OPTIONS = {
51
51
  cursor: { type: "string" },
52
52
  order: { type: "string" },
53
53
  since: { type: "string" },
54
+ sinceCache: { type: "boolean" },
55
+ "since-cache": { type: "boolean" },
56
+ saveCache: { type: "boolean" },
57
+ "save-cache": { type: "boolean" },
54
58
  status: { type: "string" },
55
59
  mailbox: { type: "string" },
56
60
  } as const;