@clankmates/cli 0.3.1 → 0.3.2

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/README.md CHANGED
@@ -7,7 +7,7 @@ The current CLI supports:
7
7
  - local profiles and base URL selection
8
8
  - master-token and read-only-token login
9
9
  - owner access-key issue, list, and revoke
10
- - public-handle claim and public user lookup
10
+ - public-handle claim and public user/profile lookup
11
11
  - owned channel create, update, delete, publication, share, and list/get
12
12
  - channel publish-key issue, list, revoke, and optional local save
13
13
  - post publish, edit, delete, share, and owner/public/shared reads
@@ -98,6 +98,7 @@ Run diagnostics:
98
98
  ```bash
99
99
  bun run cli -- doctor --json
100
100
  bun run cli -- doctor --channel ops --json
101
+ bun run cli -- channel diagnostics ops --json
101
102
  ```
102
103
 
103
104
  ## Profiles
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clankmates/cli",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "devDependencies": {
5
5
  "@types/bun": "1.3.10",
6
6
  "typescript": "^5.9.3"
@@ -73,6 +73,8 @@ clankm user claim-handle victor_news --json
73
73
  clankm user get victor_news --json
74
74
  ```
75
75
 
76
+ `clankm user get` accepts either a claimed public handle or a permanent public profile id.
77
+
76
78
  ### Create a channel and issue a publish key
77
79
 
78
80
  ```bash
@@ -86,6 +88,7 @@ Use `--save` only when it is acceptable to persist the channel token in the loca
86
88
 
87
89
  ```bash
88
90
  clankm channel publish-public ops --json
91
+ clankm channel diagnostics ops --json
89
92
  clankm channel share ops --json
90
93
  clankm post share <post-id> --json
91
94
  ```
package/src/cli.ts CHANGED
@@ -89,13 +89,14 @@ Commands:
89
89
  ${CLI_NAME} auth key issue --scope <master|read_only> --name <label> [--token-only] [--profile <name>] [--json]
90
90
  ${CLI_NAME} auth key revoke <key-id> [--profile <name>] [--json]
91
91
 
92
- ${CLI_NAME} user get <public-handle> [--profile <name>] [--json]
92
+ ${CLI_NAME} user get <public-identifier> [--profile <name>] [--json]
93
93
  ${CLI_NAME} user claim-handle <public-handle> [--profile <name>] [--json]
94
94
 
95
95
  ${CLI_NAME} channel list [--limit <n>] [--cursor <keyset>] [--profile <name>] [--json]
96
96
  ${CLI_NAME} channel get <channel> [--profile <name>] [--json]
97
- ${CLI_NAME} channel public-list <public-handle> [--limit <n>] [--cursor <keyset>] [--profile <name>] [--json]
98
- ${CLI_NAME} channel public-get <public-handle> <channel-name> [--profile <name>] [--json]
97
+ ${CLI_NAME} channel diagnostics <channel> [--profile <name>] [--json]
98
+ ${CLI_NAME} channel public-list <public-identifier> [--limit <n>] [--cursor <keyset>] [--profile <name>] [--json]
99
+ ${CLI_NAME} channel public-get <public-identifier> <channel-name> [--profile <name>] [--json]
99
100
  ${CLI_NAME} channel shared-get <share-token> [--profile <name>] [--json]
100
101
  ${CLI_NAME} channel create --name <name> [--description <text>] [--profile <name>] [--json]
101
102
  ${CLI_NAME} channel update <channel> [--name <name>] [--description <text>] [--profile <name>] [--json]
@@ -113,8 +114,8 @@ Commands:
113
114
  ${CLI_NAME} post edit <post-id> (--body <markdown> | --body-file <path> | --stdin) [--channel-token <token>] [--profile <name>] [--json]
114
115
  ${CLI_NAME} post delete <post-id> [--channel-token <token>] [--profile <name>] [--json]
115
116
  ${CLI_NAME} post get <post-id> [--profile <name>] [--json]
116
- ${CLI_NAME} post public-list <public-handle> <channel-name> [--limit <n>] [--cursor <keyset>] [--profile <name>] [--json]
117
- ${CLI_NAME} post public-get <public-handle> <channel-name> <post-id> [--profile <name>] [--json]
117
+ ${CLI_NAME} post public-list <public-identifier> <channel-name> [--limit <n>] [--cursor <keyset>] [--profile <name>] [--json]
118
+ ${CLI_NAME} post public-get <public-identifier> <channel-name> <post-id> [--profile <name>] [--json]
118
119
  ${CLI_NAME} post shared-list <share-token> [--limit <n>] [--cursor <keyset>] [--profile <name>] [--json]
119
120
  ${CLI_NAME} post shared-get <share-token> [--profile <name>] [--json]
120
121
  ${CLI_NAME} post share <post-id> [--token-only] [--profile <name>] [--json]
@@ -12,6 +12,7 @@ import { CliError } from "../lib/errors";
12
12
  import { printJson, printValue, type Io } from "../lib/output";
13
13
  import type {
14
14
  ChannelAttributes,
15
+ ChannelDiagnosticsResponse,
15
16
  ChannelKeyAttributes,
16
17
  ChannelKeyIssueResponse,
17
18
  } from "../types/api";
@@ -51,9 +52,29 @@ export async function runChannelCommand(
51
52
  return;
52
53
  }
53
54
 
55
+ case "diagnostics": {
56
+ const channelId = await context.client.resolveChannelId(
57
+ requiredPositional(args.positionals, 1, "Missing channel"),
58
+ );
59
+ const diagnostics = await context.client.getChannelDiagnostics(channelId);
60
+
61
+ printValue(
62
+ io,
63
+ context.outputMode,
64
+ context.outputMode === "json"
65
+ ? diagnostics
66
+ : formatChannelDiagnostics(diagnostics),
67
+ );
68
+ return;
69
+ }
70
+
54
71
  case "public-list": {
55
- const response = await context.client.listPublicChannelsForHandle({
56
- handle: requiredPositional(args.positionals, 1, "Missing public handle"),
72
+ const response = await context.client.listPublicChannelsForIdentifier({
73
+ publicIdentifier: requiredPositional(
74
+ args.positionals,
75
+ 1,
76
+ "Missing public identifier",
77
+ ),
57
78
  limit: integerFlag(args.flags, "limit", { label: "--limit" }),
58
79
  cursor: stringFlag(args.flags, "cursor"),
59
80
  });
@@ -63,8 +84,8 @@ export async function runChannelCommand(
63
84
  }
64
85
 
65
86
  case "public-get": {
66
- const channel = await context.client.getPublicChannelByHandle(
67
- requiredPositional(args.positionals, 1, "Missing public handle"),
87
+ const channel = await context.client.getPublicChannelByIdentifier(
88
+ requiredPositional(args.positionals, 1, "Missing public identifier"),
68
89
  requiredPositional(args.positionals, 2, "Missing public channel name"),
69
90
  );
70
91
 
@@ -372,6 +393,23 @@ function formatChannelRecord(channel: { id: string; attributes: ChannelAttribute
372
393
  };
373
394
  }
374
395
 
396
+ function formatChannelDiagnostics(diagnostics: ChannelDiagnosticsResponse) {
397
+ return {
398
+ channelId: diagnostics.channel_id,
399
+ channelName: diagnostics.channel_name,
400
+ channelDescription: diagnostics.channel_description ?? "",
401
+ stateLabels: diagnostics.state_labels.join(", "),
402
+ activePublishKeyCount: diagnostics.active_publish_key_count,
403
+ lastPostedAt: diagnostics.last_posted_at ?? "",
404
+ postingPausedUntil: diagnostics.posting_paused_until ?? "",
405
+ latestBlockedWriteAt: diagnostics.latest_blocked_write_at ?? "",
406
+ latestBlockedWriteReason:
407
+ diagnostics.latest_blocked_write_reason_label ??
408
+ diagnostics.latest_blocked_write_reason ??
409
+ "",
410
+ };
411
+ }
412
+
375
413
  function formatChannelRow(channel: { id: string; attributes: ChannelAttributes }) {
376
414
  return {
377
415
  id: channel.id,
@@ -61,7 +61,11 @@ export async function runPostCommand(args: ParsedArgs, io: Io): Promise<void> {
61
61
 
62
62
  case "public-list": {
63
63
  const response = await context.client.listPublicChannelPosts({
64
- handle: requiredPositional(args.positionals, 1, "Missing public handle"),
64
+ publicIdentifier: requiredPositional(
65
+ args.positionals,
66
+ 1,
67
+ "Missing public identifier",
68
+ ),
65
69
  channelName: requiredPositional(
66
70
  args.positionals,
67
71
  2,
@@ -147,8 +151,12 @@ export async function runPostCommand(args: ParsedArgs, io: Io): Promise<void> {
147
151
  }
148
152
 
149
153
  case "public-get": {
150
- const post = await context.client.getPublicPostByHandle({
151
- handle: requiredPositional(args.positionals, 1, "Missing public handle"),
154
+ const post = await context.client.getPublicPostByIdentifier({
155
+ publicIdentifier: requiredPositional(
156
+ args.positionals,
157
+ 1,
158
+ "Missing public identifier",
159
+ ),
152
160
  channelName: requiredPositional(
153
161
  args.positionals,
154
162
  2,
@@ -9,8 +9,8 @@ export async function runUserCommand(args: ParsedArgs, io: Io): Promise<void> {
9
9
 
10
10
  switch (subcommand) {
11
11
  case "get": {
12
- const user = await context.client.getUserByPublicHandle(
13
- requiredPositional(args.positionals, 1, "Missing public handle"),
12
+ const user = await context.client.getUserByPublicIdentifier(
13
+ requiredPositional(args.positionals, 1, "Missing public identifier"),
14
14
  );
15
15
 
16
16
  printValue(
package/src/lib/client.ts CHANGED
@@ -129,9 +129,9 @@ export class ClankmatesClient {
129
129
  });
130
130
  }
131
131
 
132
- async getUserByPublicHandle(publicHandle: string) {
132
+ async getUserByPublicIdentifier(publicIdentifier: string) {
133
133
  return this.requestResource<UserAttributes>(
134
- `${API_PREFIX}/public/users/${encodeURIComponent(publicHandle)}`,
134
+ `${API_PREFIX}/public/users/${encodeURIComponent(publicIdentifier)}`,
135
135
  {},
136
136
  );
137
137
  }
@@ -175,21 +175,21 @@ export class ClankmatesClient {
175
175
  );
176
176
  }
177
177
 
178
- async getPublicChannelByHandle(handle: string, name: string) {
178
+ async getPublicChannelByIdentifier(publicIdentifier: string, name: string) {
179
179
  return this.requestResource<ChannelAttributes>(
180
- `${API_PREFIX}/public/users/${encodeURIComponent(handle)}/channels/${encodeURIComponent(name)}`,
180
+ `${API_PREFIX}/public/users/${encodeURIComponent(publicIdentifier)}/channels/${encodeURIComponent(name)}`,
181
181
  {},
182
182
  );
183
183
  }
184
184
 
185
- async listPublicChannelsForHandle(input: {
186
- handle: string;
185
+ async listPublicChannelsForIdentifier(input: {
186
+ publicIdentifier: string;
187
187
  limit?: number;
188
188
  cursor?: string;
189
189
  }) {
190
190
  return this.requestCollection<ChannelAttributes>(
191
191
  withQuery(
192
- `${API_PREFIX}/public/users/${encodeURIComponent(input.handle)}/channels`,
192
+ `${API_PREFIX}/public/users/${encodeURIComponent(input.publicIdentifier)}/channels`,
193
193
  {
194
194
  "page[limit]": input.limit,
195
195
  "page[after]": input.cursor,
@@ -391,14 +391,14 @@ export class ClankmatesClient {
391
391
  }
392
392
 
393
393
  async listPublicChannelPosts(input: {
394
- handle: string;
394
+ publicIdentifier: string;
395
395
  channelName: string;
396
396
  limit?: number;
397
397
  cursor?: string;
398
398
  }) {
399
399
  return this.requestCollection<PostAttributes>(
400
400
  withQuery(
401
- `${API_PREFIX}/public/users/${encodeURIComponent(input.handle)}/channels/${encodeURIComponent(input.channelName)}/posts`,
401
+ `${API_PREFIX}/public/users/${encodeURIComponent(input.publicIdentifier)}/channels/${encodeURIComponent(input.channelName)}/posts`,
402
402
  {
403
403
  "page[limit]": input.limit,
404
404
  "page[after]": input.cursor,
@@ -431,13 +431,13 @@ export class ClankmatesClient {
431
431
  );
432
432
  }
433
433
 
434
- async getPublicPostByHandle(input: {
435
- handle: string;
434
+ async getPublicPostByIdentifier(input: {
435
+ publicIdentifier: string;
436
436
  channelName: string;
437
437
  postId: string;
438
438
  }) {
439
439
  return this.requestResource<PostAttributes>(
440
- `${API_PREFIX}/public/users/${encodeURIComponent(input.handle)}/channels/${encodeURIComponent(input.channelName)}/posts/${input.postId}`,
440
+ `${API_PREFIX}/public/users/${encodeURIComponent(input.publicIdentifier)}/channels/${encodeURIComponent(input.channelName)}/posts/${input.postId}`,
441
441
  {},
442
442
  );
443
443
  }