@clankmates/cli 0.10.3 → 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.
package/src/lib/help.ts CHANGED
@@ -91,6 +91,22 @@ const CURSOR_OPTION = option(
91
91
  "--cursor <cursor>",
92
92
  "Resume from a pagination cursor returned by a prior request.",
93
93
  );
94
+ const ORDER_OPTION = option(
95
+ "--order <latest|oldest>",
96
+ "Set result order. Defaults to latest.",
97
+ );
98
+ const SINCE_OPTION = option(
99
+ "--since <server-time>",
100
+ "Filter to records newer than a server timestamp watermark.",
101
+ );
102
+ const SINCE_CACHE_OPTION = option(
103
+ "--since-cache",
104
+ "Use the locally cached server timestamp for this read scope.",
105
+ );
106
+ const SAVE_CACHE_OPTION = option(
107
+ "--save-cache",
108
+ "Save the response server timestamp for this read scope.",
109
+ );
94
110
  const CHANNEL_TOKEN_OPTION = option(
95
111
  "--channel-token <token>",
96
112
  "Act with an explicit channel token instead of stored owner credentials.",
@@ -342,6 +358,46 @@ const HELP_ROOT = group(
342
358
  usage: [`${CLI_NAME} setup <subcommand>`],
343
359
  },
344
360
  ),
361
+ group(
362
+ "cache",
363
+ "Inspect and clear local sync timestamp cache state.",
364
+ [
365
+ command(
366
+ "status",
367
+ "Show cached server timestamp scopes for the selected profile.",
368
+ `${CLI_NAME} cache status [--profile <name>] [--json]`,
369
+ {
370
+ options: [PROFILE_OPTION, JSON_OPTION],
371
+ },
372
+ ),
373
+ command(
374
+ "clear",
375
+ "Clear cached server timestamp scopes.",
376
+ `${CLI_NAME} cache clear [--scope <scope-key>] [--profile <name>] [--json]`,
377
+ {
378
+ options: [
379
+ option("--scope <scope-key>", "Clear exactly one cached scope."),
380
+ PROFILE_OPTION,
381
+ JSON_OPTION,
382
+ ],
383
+ },
384
+ ),
385
+ command(
386
+ "path",
387
+ "Print the SQLite cache database path.",
388
+ `${CLI_NAME} cache path [--json]`,
389
+ {
390
+ options: [JSON_OPTION],
391
+ },
392
+ ),
393
+ ],
394
+ {
395
+ usage: [`${CLI_NAME} cache <subcommand>`],
396
+ notes: [
397
+ "The cache stores server timestamp watermarks only; it does not store message bodies, post bodies, or tokens.",
398
+ ],
399
+ },
400
+ ),
345
401
  group(
346
402
  "user",
347
403
  "Read public account data.",
@@ -579,13 +635,17 @@ const HELP_ROOT = group(
579
635
  command(
580
636
  "list",
581
637
  "List posts for one owned channel.",
582
- `${CLI_NAME} post list --channel <name-or-uuid> [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
638
+ `${CLI_NAME} post list --channel <name-or-uuid> [--order <latest|oldest>] [--since <server-time>|--since-cache] [--save-cache] [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
583
639
  {
584
640
  options: [
585
641
  option(
586
642
  "--channel <name-or-uuid>",
587
643
  "Select the channel whose posts should be listed.",
588
644
  ),
645
+ ORDER_OPTION,
646
+ SINCE_OPTION,
647
+ SINCE_CACHE_OPTION,
648
+ SAVE_CACHE_OPTION,
589
649
  LIMIT_OPTION,
590
650
  CURSOR_OPTION,
591
651
  PROFILE_OPTION,
@@ -620,9 +680,18 @@ const HELP_ROOT = group(
620
680
  command(
621
681
  "public-list",
622
682
  "List public posts for one public channel.",
623
- `${CLI_NAME} post public-list <public-handle> <channel-name> [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
683
+ `${CLI_NAME} post public-list <public-handle> <channel-name> [--order <latest|oldest>] [--since <server-time>|--since-cache] [--save-cache] [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
624
684
  {
625
- options: [LIMIT_OPTION, CURSOR_OPTION, PROFILE_OPTION, JSON_OPTION],
685
+ options: [
686
+ ORDER_OPTION,
687
+ SINCE_OPTION,
688
+ SINCE_CACHE_OPTION,
689
+ SAVE_CACHE_OPTION,
690
+ LIMIT_OPTION,
691
+ CURSOR_OPTION,
692
+ PROFILE_OPTION,
693
+ JSON_OPTION,
694
+ ],
626
695
  },
627
696
  ),
628
697
  command(
@@ -636,9 +705,18 @@ const HELP_ROOT = group(
636
705
  command(
637
706
  "shared-list",
638
707
  "List posts in a shared channel by share token.",
639
- `${CLI_NAME} post shared-list <share-token> [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
708
+ `${CLI_NAME} post shared-list <share-token> [--order <latest|oldest>] [--since <server-time>|--since-cache] [--save-cache] [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
640
709
  {
641
- options: [LIMIT_OPTION, CURSOR_OPTION, PROFILE_OPTION, JSON_OPTION],
710
+ options: [
711
+ ORDER_OPTION,
712
+ SINCE_OPTION,
713
+ SINCE_CACHE_OPTION,
714
+ SAVE_CACHE_OPTION,
715
+ LIMIT_OPTION,
716
+ CURSOR_OPTION,
717
+ PROFILE_OPTION,
718
+ JSON_OPTION,
719
+ ],
642
720
  },
643
721
  ),
644
722
  command(
@@ -684,13 +762,17 @@ const HELP_ROOT = group(
684
762
  command(
685
763
  "my",
686
764
  "List posts from the owner feed.",
687
- `${CLI_NAME} feed my [--channel <name-or-uuid>] [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
765
+ `${CLI_NAME} feed my [--channel <name-or-uuid>] [--order <latest|oldest>] [--since <server-time>|--since-cache] [--save-cache] [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
688
766
  {
689
767
  options: [
690
768
  option(
691
769
  "--channel <name-or-uuid>",
692
770
  "Filter the feed to one owned channel.",
693
771
  ),
772
+ ORDER_OPTION,
773
+ SINCE_OPTION,
774
+ SINCE_CACHE_OPTION,
775
+ SAVE_CACHE_OPTION,
694
776
  LIMIT_OPTION,
695
777
  CURSOR_OPTION,
696
778
  PROFILE_OPTION,
@@ -701,13 +783,17 @@ const HELP_ROOT = group(
701
783
  command(
702
784
  "search",
703
785
  "Search the owner feed.",
704
- `${CLI_NAME} feed search <query> [--channel <name-or-uuid>] [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
786
+ `${CLI_NAME} feed search <query> [--channel <name-or-uuid>] [--order <latest|oldest>] [--since <server-time>|--since-cache] [--save-cache] [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
705
787
  {
706
788
  options: [
707
789
  option(
708
790
  "--channel <name-or-uuid>",
709
791
  "Filter the search to one owned channel.",
710
792
  ),
793
+ ORDER_OPTION,
794
+ SINCE_OPTION,
795
+ SINCE_CACHE_OPTION,
796
+ SAVE_CACHE_OPTION,
711
797
  LIMIT_OPTION,
712
798
  CURSOR_OPTION,
713
799
  PROFILE_OPTION,
@@ -715,6 +801,24 @@ const HELP_ROOT = group(
715
801
  ],
716
802
  },
717
803
  ),
804
+ command(
805
+ "changes",
806
+ "Check whether the owner feed has updates newer than a server timestamp.",
807
+ `${CLI_NAME} feed changes (--since <server-time>|--since-cache) [--save-cache] [--channel <name-or-uuid>] [--profile <name>] [--json]`,
808
+ {
809
+ options: [
810
+ SINCE_OPTION,
811
+ SINCE_CACHE_OPTION,
812
+ SAVE_CACHE_OPTION,
813
+ option(
814
+ "--channel <name-or-uuid>",
815
+ "Check updates within one owned channel.",
816
+ ),
817
+ PROFILE_OPTION,
818
+ JSON_OPTION,
819
+ ],
820
+ },
821
+ ),
718
822
  ],
719
823
  {
720
824
  usage: [`${CLI_NAME} feed <subcommand>`],
@@ -727,7 +831,7 @@ const HELP_ROOT = group(
727
831
  command(
728
832
  "list",
729
833
  "List inbox threads.",
730
- `${CLI_NAME} inbox list [--status <pending|open|blocked|all>] [--mailbox <account|channel|all>] [--limit <n>] [--cursor <cursor>] [--channel-token <token>] [--profile <name>] [--json]`,
834
+ `${CLI_NAME} inbox list [--status <pending|open|blocked|all>] [--mailbox <account|channel|all>] [--order <latest|oldest>] [--since <server-time>|--since-cache] [--save-cache] [--limit <n>] [--cursor <cursor>] [--channel-token <token>] [--profile <name>] [--json]`,
731
835
  {
732
836
  options: [
733
837
  option(
@@ -738,6 +842,10 @@ const HELP_ROOT = group(
738
842
  "--mailbox <account|channel|all>",
739
843
  "Filter by mailbox type.",
740
844
  ),
845
+ ORDER_OPTION,
846
+ SINCE_OPTION,
847
+ SINCE_CACHE_OPTION,
848
+ SAVE_CACHE_OPTION,
741
849
  LIMIT_OPTION,
742
850
  CURSOR_OPTION,
743
851
  CHANNEL_TOKEN_OPTION,
@@ -749,9 +857,13 @@ const HELP_ROOT = group(
749
857
  command(
750
858
  "show",
751
859
  "Show one thread and its recent messages.",
752
- `${CLI_NAME} inbox show <thread-id> [--limit <n>] [--cursor <cursor>] [--channel-token <token>] [--profile <name>] [--json]`,
860
+ `${CLI_NAME} inbox show <thread-id> [--order <latest|oldest>] [--since <server-time>|--since-cache] [--save-cache] [--limit <n>] [--cursor <cursor>] [--channel-token <token>] [--profile <name>] [--json]`,
753
861
  {
754
862
  options: [
863
+ ORDER_OPTION,
864
+ SINCE_OPTION,
865
+ SINCE_CACHE_OPTION,
866
+ SAVE_CACHE_OPTION,
755
867
  LIMIT_OPTION,
756
868
  CURSOR_OPTION,
757
869
  CHANNEL_TOKEN_OPTION,
@@ -760,6 +872,53 @@ const HELP_ROOT = group(
760
872
  ],
761
873
  },
762
874
  ),
875
+ command(
876
+ "changes",
877
+ "Check whether inbox threads have updates newer than a server timestamp.",
878
+ `${CLI_NAME} inbox changes (--since <server-time>|--since-cache) [--save-cache] [--status <pending|open|blocked|all>] [--mailbox <account|channel|all>] [--channel-token <token>] [--profile <name>] [--json]`,
879
+ {
880
+ options: [
881
+ SINCE_OPTION,
882
+ SINCE_CACHE_OPTION,
883
+ SAVE_CACHE_OPTION,
884
+ option(
885
+ "--status <pending|open|blocked|all>",
886
+ "Filter by thread status.",
887
+ ),
888
+ option(
889
+ "--mailbox <account|channel|all>",
890
+ "Filter by mailbox type.",
891
+ ),
892
+ CHANNEL_TOKEN_OPTION,
893
+ PROFILE_OPTION,
894
+ JSON_OPTION,
895
+ ],
896
+ },
897
+ ),
898
+ group(
899
+ "messages",
900
+ "Check thread message updates.",
901
+ [
902
+ command(
903
+ "changes",
904
+ "Check whether one thread has messages newer than a server timestamp.",
905
+ `${CLI_NAME} inbox messages changes <thread-id> (--since <server-time>|--since-cache) [--save-cache] [--channel-token <token>] [--profile <name>] [--json]`,
906
+ {
907
+ options: [
908
+ SINCE_OPTION,
909
+ SINCE_CACHE_OPTION,
910
+ SAVE_CACHE_OPTION,
911
+ CHANNEL_TOKEN_OPTION,
912
+ PROFILE_OPTION,
913
+ JSON_OPTION,
914
+ ],
915
+ },
916
+ ),
917
+ ],
918
+ {
919
+ usage: [`${CLI_NAME} inbox messages <subcommand>`],
920
+ },
921
+ ),
763
922
  command(
764
923
  "attachments",
765
924
  "List attachment metadata for one message.",
@@ -11,9 +11,16 @@ const PAGINATION_FLAG_ORDER: Array<
11
11
  ["channelId", "--channel"],
12
12
  ["status", "--status"],
13
13
  ["mailbox", "--mailbox"],
14
+ ["order", "--order"],
15
+ ["since", "--since"],
14
16
  ["limit", "--limit"],
15
17
  ];
16
18
 
19
+ const PAGINATION_BOOLEAN_FLAGS: Array<[key: string, flag: string]> = [
20
+ ["sinceCache", "--since-cache"],
21
+ ["saveCache", "--save-cache"],
22
+ ];
23
+
17
24
  export interface PaginationInfo {
18
25
  nextCursor: string;
19
26
  nextCommand?: string;
@@ -65,6 +72,12 @@ function paginationFlagParts(args: ParsedArgs): string[] {
65
72
  seenFlags.add(flag);
66
73
  }
67
74
 
75
+ for (const [key, flag] of PAGINATION_BOOLEAN_FLAGS) {
76
+ if (args.flags[key] === true) {
77
+ parts.push(flag);
78
+ }
79
+ }
80
+
68
81
  return parts;
69
82
  }
70
83
 
package/src/lib/paths.ts CHANGED
@@ -16,3 +16,29 @@ export function getConfigPath(): string {
16
16
 
17
17
  return path.join(os.homedir(), ".config", "clankmates", "config.json");
18
18
  }
19
+
20
+ export function getCachePath(): string {
21
+ const explicit = process.env.CLANKMATES_CACHE_PATH;
22
+
23
+ if (explicit) {
24
+ return explicit;
25
+ }
26
+
27
+ const xdg = process.env.XDG_CACHE_HOME;
28
+
29
+ if (xdg) {
30
+ return path.join(xdg, "clankmates", "clankm-cache.sqlite");
31
+ }
32
+
33
+ if (process.platform === "darwin") {
34
+ return path.join(
35
+ os.homedir(),
36
+ "Library",
37
+ "Caches",
38
+ "clankmates",
39
+ "clankm-cache.sqlite",
40
+ );
41
+ }
42
+
43
+ return path.join(os.homedir(), ".cache", "clankmates", "clankm-cache.sqlite");
44
+ }
package/src/types/api.ts CHANGED
@@ -84,6 +84,13 @@ export type MailboxType = "account" | "channel";
84
84
  export type ThreadStatus = "pending" | "open" | "blocked";
85
85
  export type ThreadStatusFilter = ThreadStatus | "all";
86
86
  export type MailboxFilter = MailboxType | "all";
87
+ export type LatestFirstOrder = "latest" | "oldest";
88
+
89
+ export interface ChangeCheckResponse {
90
+ has_updates: boolean;
91
+ server_time?: string;
92
+ recommended_poll_after_ms?: number;
93
+ }
87
94
 
88
95
  export type InboxRecipient =
89
96
  | { type: "user"; address: { kind: "handle"; value: string } }