@fulldivevr/workcord-cli 1.0.0 → 1.1.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.
Files changed (81) hide show
  1. package/README.md +88 -30
  2. package/dist/auth.js +38 -4
  3. package/dist/cli.js +3 -1
  4. package/dist/client.js +21 -12
  5. package/dist/commands/auth.js +33 -14
  6. package/dist/commands/challenges.js +2 -7
  7. package/dist/commands/custom-agents.js +3 -8
  8. package/dist/commands/dm.js +2 -3
  9. package/dist/commands/health.js +29 -0
  10. package/dist/commands/messages.js +8 -21
  11. package/dist/commands/room-agents.js +2 -7
  12. package/dist/commands/rooms.js +24 -31
  13. package/dist/commands/users.js +4 -9
  14. package/dist/commands/whoami.js +24 -7
  15. package/dist/config.js +34 -0
  16. package/dist/generated/commands/activity.js +3 -6
  17. package/dist/generated/commands/ai.js +3 -6
  18. package/dist/generated/commands/ambassador.js +3 -6
  19. package/dist/generated/commands/apple-iap.js +4 -9
  20. package/dist/generated/commands/attribution.js +6 -15
  21. package/dist/generated/commands/auth.js +9 -24
  22. package/dist/generated/commands/challenges.js +13 -36
  23. package/dist/generated/commands/clips.js +3 -6
  24. package/dist/generated/commands/contact-match.js +7 -18
  25. package/dist/generated/commands/content-crawler.js +2 -3
  26. package/dist/generated/commands/custom-agents.js +22 -63
  27. package/dist/generated/commands/desktop-releases.js +5 -12
  28. package/dist/generated/commands/discover.js +9 -24
  29. package/dist/generated/commands/dm.js +10 -27
  30. package/dist/generated/commands/drafts.js +3 -6
  31. package/dist/generated/commands/embed.js +3 -6
  32. package/dist/generated/commands/explore.js +2 -3
  33. package/dist/generated/commands/feed.js +4 -9
  34. package/dist/generated/commands/feedback.js +2 -3
  35. package/dist/generated/commands/gamification.js +3 -6
  36. package/dist/generated/commands/google-play-iap.js +4 -9
  37. package/dist/generated/commands/internal.js +9 -24
  38. package/dist/generated/commands/interview.js +4 -9
  39. package/dist/generated/commands/invite-redirect.js +2 -3
  40. package/dist/generated/commands/jesuscord-admin.js +3 -6
  41. package/dist/generated/commands/join.js +2 -3
  42. package/dist/generated/commands/kits.js +7 -18
  43. package/dist/generated/commands/meetings.js +6 -15
  44. package/dist/generated/commands/message-folders.js +5 -12
  45. package/dist/generated/commands/messages.js +17 -48
  46. package/dist/generated/commands/one-emulator.js +2 -3
  47. package/dist/generated/commands/pdf-export.js +2 -3
  48. package/dist/generated/commands/pin-folders.js +5 -12
  49. package/dist/generated/commands/pinned-messages.js +4 -9
  50. package/dist/generated/commands/polls.js +6 -15
  51. package/dist/generated/commands/premium-feeds.js +2 -3
  52. package/dist/generated/commands/processors.js +2 -3
  53. package/dist/generated/commands/questions.js +3 -6
  54. package/dist/generated/commands/referrals.js +2 -3
  55. package/dist/generated/commands/reports.js +2 -3
  56. package/dist/generated/commands/room-a2-a.js +6 -15
  57. package/dist/generated/commands/room-agents.js +13 -36
  58. package/dist/generated/commands/room-invites.js +9 -24
  59. package/dist/generated/commands/room-owned-agent.js +3 -6
  60. package/dist/generated/commands/room-page.js +2 -3
  61. package/dist/generated/commands/rooms.js +45 -132
  62. package/dist/generated/commands/saved-messages.js +4 -9
  63. package/dist/generated/commands/saved-stories.js +7 -18
  64. package/dist/generated/commands/search.js +2 -3
  65. package/dist/generated/commands/shadow-home-agent.js +3 -6
  66. package/dist/generated/commands/shadow.js +5 -12
  67. package/dist/generated/commands/share-cards.js +4 -9
  68. package/dist/generated/commands/share.js +2 -3
  69. package/dist/generated/commands/sponsors.js +2 -3
  70. package/dist/generated/commands/stories.js +12 -33
  71. package/dist/generated/commands/story-by-id.js +2 -3
  72. package/dist/generated/commands/submissions.js +4 -9
  73. package/dist/generated/commands/subscriptions.js +8 -21
  74. package/dist/generated/commands/tips.js +3 -6
  75. package/dist/generated/commands/users.js +16 -45
  76. package/dist/generated/commands/voice-token.js +2 -3
  77. package/dist/generated/commands/well-known.js +3 -6
  78. package/dist/generated/commands/wrapped.js +2 -3
  79. package/dist/generated/index.js +0 -2
  80. package/package.json +3 -2
  81. package/dist/generated/commands/health.js +0 -32
@@ -1,3 +1,4 @@
1
+ import { actingUserId } from "../auth.js";
1
2
  import { call } from "../client.js";
2
3
  import { getOrCreateGroup } from "./_group.js";
3
4
  const MAX_LIMIT = 500;
@@ -113,9 +114,7 @@ export function registerMessages(program) {
113
114
  .option("--attachments <urls>", "comma-separated GCS URLs (use `workcord rooms upload-image-file` to get URLs first)")
114
115
  .option("--no-shadow-guidance", "do not opt in to Shadow guidance cards")
115
116
  .action(async (opts) => {
116
- const { as } = program.opts();
117
- if (!as)
118
- throw new Error("--as <userId> is required");
117
+ const as = actingUserId(program);
119
118
  const mentions = await resolveMentions(opts.room, as, opts.mentionUser);
120
119
  const content = mentions.length > 0 ? `${mentions.map((m) => `@${m.name}`).join(" ")} ${opts.text}` : opts.text;
121
120
  const body = {
@@ -143,9 +142,7 @@ export function registerMessages(program) {
143
142
  .option("--after <iso>", "only messages with sentAt > this ISO timestamp; overrides --cursor server-side")
144
143
  .option("--filter <filter>", `one of: ${Array.from(MESSAGE_FILTERS).join(", ")}`)
145
144
  .action(async (opts) => {
146
- const { as } = program.opts();
147
- if (!as)
148
- throw new Error("--as <userId> is required");
145
+ const as = actingUserId(program);
149
146
  const data = await call({
150
147
  method: "GET",
151
148
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}/messages`,
@@ -169,9 +166,7 @@ export function registerMessages(program) {
169
166
  .option("--limit <n>", `page size, 1-${MAX_PAGE_LIMIT}`, "20")
170
167
  .option("--cursor <iso>", "pagination cursor from the previous page's cursor")
171
168
  .action(async (opts) => {
172
- const { as } = program.opts();
173
- if (!as)
174
- throw new Error("--as <userId> is required");
169
+ const as = actingUserId(program);
175
170
  const data = await call({
176
171
  method: "GET",
177
172
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}/messages/${encodeURIComponent(opts.message)}/thread`,
@@ -190,9 +185,7 @@ export function registerMessages(program) {
190
185
  .requiredOption("--room <roomId>", "target room id")
191
186
  .requiredOption("--message <messageId>", "thread root message id")
192
187
  .action(async (opts) => {
193
- const { as } = program.opts();
194
- if (!as)
195
- throw new Error("--as <userId> is required");
188
+ const as = actingUserId(program);
196
189
  const data = await call({
197
190
  method: "POST",
198
191
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}/messages/${encodeURIComponent(opts.message)}/thread/read`,
@@ -209,9 +202,7 @@ export function registerMessages(program) {
209
202
  .option("--limit <n>", "max messages per page (server caps at 100)", "50")
210
203
  .option("--max-pages <n>", "safety cap on pages walked back", "20")
211
204
  .action(async (opts) => {
212
- const { as } = program.opts();
213
- if (!as)
214
- throw new Error("--as <userId> is required");
205
+ const as = actingUserId(program);
215
206
  const sinceMs = new Date(opts.since).getTime();
216
207
  if (Number.isNaN(sinceMs))
217
208
  throw new Error(`--since not a valid ISO timestamp: ${opts.since}`);
@@ -259,9 +250,7 @@ export function registerMessages(program) {
259
250
  .option("--inbox-category <value>", "room inbox category filter")
260
251
  .option("--no-shadow-guidance", "do not opt in to Shadow guidance cards")
261
252
  .action(async (opts) => {
262
- const { as } = program.opts();
263
- if (!as)
264
- throw new Error("--as <userId> is required");
253
+ const as = actingUserId(program);
265
254
  const limit = parsePositiveInt(opts.limit, "--limit", MAX_LIMIT);
266
255
  const perRoomLimit = parsePositiveInt(opts.perRoomLimit, "--per-room-limit", MAX_PAGE_LIMIT);
267
256
  const roomPageLimit = parsePositiveInt(opts.roomPageLimit, "--room-page-limit", MAX_PAGE_LIMIT);
@@ -345,9 +334,7 @@ export function registerMessages(program) {
345
334
  .requiredOption("--message <messageId>", "target message")
346
335
  .requiredOption("--emoji <type>", 'reaction type — emoji or id (e.g. "👍" or "thumbs_up")')
347
336
  .action(async (opts) => {
348
- const { as } = program.opts();
349
- if (!as)
350
- throw new Error("--as <userId> is required");
337
+ const as = actingUserId(program);
351
338
  const data = await call({
352
339
  method: "POST",
353
340
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}/messages/${encodeURIComponent(opts.message)}/reactions`,
@@ -1,11 +1,6 @@
1
+ import { actingUserId } from "../auth.js";
1
2
  import { call } from "../client.js";
2
3
  import { getOrCreateGroup } from "./_group.js";
3
- function currentUser(program) {
4
- const { as } = program.opts();
5
- if (!as)
6
- throw new Error("--as <userId> is required");
7
- return as;
8
- }
9
4
  function bool(v, name) {
10
5
  if (v === undefined)
11
6
  return undefined;
@@ -24,7 +19,7 @@ export function registerRoomAgents(program) {
24
19
  .requiredOption("--agent <agentId>", "hosted custom/system agent id")
25
20
  .option("--reply-in-thread <true|false>", "whether the agent replies in threads")
26
21
  .action(async (opts) => {
27
- const asUserId = currentUser(program);
22
+ const asUserId = actingUserId(program);
28
23
  const installed = (await call({
29
24
  method: "POST",
30
25
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}/agents/install/${encodeURIComponent(opts.agent)}`,
@@ -1,6 +1,7 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import { basename, extname } from "node:path";
3
3
  import { callMultipart } from "../client.js";
4
+ import { actingUserId } from "../auth.js";
4
5
  import { call } from "../client.js";
5
6
  import { getOrCreateGroup } from "./_group.js";
6
7
  const IMAGE_MIME = {
@@ -12,12 +13,6 @@ const IMAGE_MIME = {
12
13
  };
13
14
  const DEFAULT_ROOM_LIMIT = 50;
14
15
  const MAX_ROOM_LIMIT = 100;
15
- function currentUser(program) {
16
- const { as } = program.opts();
17
- if (!as)
18
- throw new Error("--as <userId> is required");
19
- return as;
20
- }
21
16
  function parseLimit(v) {
22
17
  const limit = Number(v);
23
18
  if (!Number.isInteger(limit) || limit < 1 || limit > MAX_ROOM_LIMIT) {
@@ -229,7 +224,7 @@ export function registerRooms(program) {
229
224
  .option("--inbox-category <value>", "inbox category filter")
230
225
  .option("--no-shadow-guidance", "do not opt in to Shadow guidance cards")
231
226
  .action(async (opts) => {
232
- const asUserId = currentUser(program);
227
+ const asUserId = actingUserId(program);
233
228
  const limit = parseLimit(opts.limit);
234
229
  if (opts.all && opts.cursor)
235
230
  throw new Error("Use either --all or --cursor, not both");
@@ -274,7 +269,7 @@ export function registerRooms(program) {
274
269
  .option("--sort <value>", "sort: active, new, best, trending")
275
270
  .option("--tags <items>", "comma-separated tag filters")
276
271
  .action(async (opts) => {
277
- const asUserId = currentUser(program);
272
+ const asUserId = actingUserId(program);
278
273
  const limit = parseLimit(opts.limit);
279
274
  const page = parsePage(opts.page);
280
275
  if (opts.all && (opts.cursor || page !== undefined)) {
@@ -355,7 +350,7 @@ export function registerRooms(program) {
355
350
  sort: opts.sort,
356
351
  tags: opts.tags,
357
352
  },
358
- asUserId: currentUser(program),
353
+ asUserId: actingUserId(program),
359
354
  });
360
355
  process.stdout.write(JSON.stringify(normalizedRoomList(data)) + "\n");
361
356
  });
@@ -368,7 +363,7 @@ export function registerRooms(program) {
368
363
  method: "GET",
369
364
  path: "/api/v1/discover/rooms/enriched",
370
365
  query: { sort: "trending", limit: parseLimit(opts.limit), page: 1 },
371
- asUserId: currentUser(program),
366
+ asUserId: actingUserId(program),
372
367
  });
373
368
  process.stdout.write(JSON.stringify(normalizedRoomList(data)) + "\n");
374
369
  });
@@ -383,7 +378,7 @@ export function registerRooms(program) {
383
378
  method: "GET",
384
379
  path: "/api/v1/search",
385
380
  query: { type: "rooms", q: opts.q, cursor: opts.cursor, limit: parseLimit(opts.limit) },
386
- asUserId: currentUser(program),
381
+ asUserId: actingUserId(program),
387
382
  });
388
383
  process.stdout.write(JSON.stringify(normalizedRoomList(data)) + "\n");
389
384
  });
@@ -397,7 +392,7 @@ export function registerRooms(program) {
397
392
  method: "POST",
398
393
  path: "/api/v1/rooms",
399
394
  body: roomBody(opts, "create"),
400
- asUserId: currentUser(program),
395
+ asUserId: actingUserId(program),
401
396
  });
402
397
  process.stdout.write(JSON.stringify(data) + "\n");
403
398
  });
@@ -408,7 +403,7 @@ export function registerRooms(program) {
408
403
  .requiredOption("--text <text>", "first message body")
409
404
  .option("--language <value>", "room language")
410
405
  .option("--install-agent-id <id>", "agent id to install on create"), { createOnly: true }).action(async (opts) => {
411
- const asUserId = currentUser(program);
406
+ const asUserId = actingUserId(program);
412
407
  const room = await call({
413
408
  method: "POST",
414
409
  path: "/api/v1/rooms",
@@ -438,7 +433,7 @@ export function registerRooms(program) {
438
433
  method: "PATCH",
439
434
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}`,
440
435
  body: roomBody(opts, "update"),
441
- asUserId: currentUser(program),
436
+ asUserId: actingUserId(program),
442
437
  });
443
438
  process.stdout.write(JSON.stringify(data) + "\n");
444
439
  });
@@ -450,7 +445,7 @@ export function registerRooms(program) {
450
445
  const data = await call({
451
446
  method: "DELETE",
452
447
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}`,
453
- asUserId: currentUser(program),
448
+ asUserId: actingUserId(program),
454
449
  });
455
450
  process.stdout.write(JSON.stringify(data) + "\n");
456
451
  });
@@ -466,7 +461,7 @@ export function registerRooms(program) {
466
461
  method: "POST",
467
462
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}/join`,
468
463
  body: { joinCode: opts.code, inviteToken: opts.inviteToken, ref: opts.ref },
469
- asUserId: currentUser(program),
464
+ asUserId: actingUserId(program),
470
465
  });
471
466
  process.stdout.write(JSON.stringify(data) + "\n");
472
467
  });
@@ -479,7 +474,7 @@ export function registerRooms(program) {
479
474
  const room = await call({
480
475
  method: "GET",
481
476
  path: `/api/v1/rooms/resolve-code/${encodeURIComponent(inviteToken)}`,
482
- asUserId: currentUser(program),
477
+ asUserId: actingUserId(program),
483
478
  });
484
479
  process.stdout.write(JSON.stringify(inviteResolution(inviteToken, room)) + "\n");
485
480
  });
@@ -488,7 +483,7 @@ export function registerRooms(program) {
488
483
  .description("Accept a room invite token by resolving it and joining the target room.")
489
484
  .requiredOption("--invite-token <token>", "room invite token, with or without i- prefix")
490
485
  .action(async (opts) => {
491
- const asUserId = currentUser(program);
486
+ const asUserId = actingUserId(program);
492
487
  const inviteToken = normalizeInviteToken(opts.inviteToken);
493
488
  const room = await call({
494
489
  method: "GET",
@@ -522,7 +517,7 @@ export function registerRooms(program) {
522
517
  const data = await call({
523
518
  method: "POST",
524
519
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}/leave`,
525
- asUserId: currentUser(program),
520
+ asUserId: actingUserId(program),
526
521
  });
527
522
  process.stdout.write(JSON.stringify(data) + "\n");
528
523
  });
@@ -534,7 +529,7 @@ export function registerRooms(program) {
534
529
  const data = await call({
535
530
  method: "POST",
536
531
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}/read`,
537
- asUserId: currentUser(program),
532
+ asUserId: actingUserId(program),
538
533
  });
539
534
  process.stdout.write(JSON.stringify(data) + "\n");
540
535
  });
@@ -550,7 +545,7 @@ export function registerRooms(program) {
550
545
  method: "GET",
551
546
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}/members`,
552
547
  query: { cursor: opts.cursor, limit: opts.limit, sort: opts.sort },
553
- asUserId: currentUser(program),
548
+ asUserId: actingUserId(program),
554
549
  });
555
550
  process.stdout.write(JSON.stringify(data) + "\n");
556
551
  });
@@ -563,7 +558,7 @@ export function registerRooms(program) {
563
558
  const data = await call({
564
559
  method: "DELETE",
565
560
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}/members/${encodeURIComponent(opts.user)}`,
566
- asUserId: currentUser(program),
561
+ asUserId: actingUserId(program),
567
562
  });
568
563
  process.stdout.write(JSON.stringify(data) + "\n");
569
564
  });
@@ -579,7 +574,7 @@ export function registerRooms(program) {
579
574
  method: "GET",
580
575
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}/join-requests`,
581
576
  query: { status: opts.status, cursor: opts.cursor, limit: opts.limit },
582
- asUserId: currentUser(program),
577
+ asUserId: actingUserId(program),
583
578
  });
584
579
  process.stdout.write(JSON.stringify(data) + "\n");
585
580
  });
@@ -592,7 +587,7 @@ export function registerRooms(program) {
592
587
  const data = await call({
593
588
  method: "POST",
594
589
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}/join-requests/${encodeURIComponent(opts.request)}/approve`,
595
- asUserId: currentUser(program),
590
+ asUserId: actingUserId(program),
596
591
  });
597
592
  process.stdout.write(JSON.stringify(data) + "\n");
598
593
  });
@@ -605,7 +600,7 @@ export function registerRooms(program) {
605
600
  const data = await call({
606
601
  method: "POST",
607
602
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}/join-requests/${encodeURIComponent(opts.request)}/deny`,
608
- asUserId: currentUser(program),
603
+ asUserId: actingUserId(program),
609
604
  });
610
605
  process.stdout.write(JSON.stringify(data) + "\n");
611
606
  });
@@ -617,7 +612,7 @@ export function registerRooms(program) {
617
612
  const data = await call({
618
613
  method: "POST",
619
614
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}/regenerate-join-code`,
620
- asUserId: currentUser(program),
615
+ asUserId: actingUserId(program),
621
616
  });
622
617
  process.stdout.write(JSON.stringify(data) + "\n");
623
618
  });
@@ -629,7 +624,7 @@ export function registerRooms(program) {
629
624
  const data = await call({
630
625
  method: "GET",
631
626
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}/membership`,
632
- asUserId: currentUser(program),
627
+ asUserId: actingUserId(program),
633
628
  });
634
629
  process.stdout.write(JSON.stringify(data) + "\n");
635
630
  });
@@ -646,7 +641,7 @@ export function registerRooms(program) {
646
641
  }
647
642
  const data = await callMultipart({
648
643
  path: `/api/v1/rooms/${encodeURIComponent(opts.room)}/icon`,
649
- asUserId: currentUser(program),
644
+ asUserId: actingUserId(program),
650
645
  file: {
651
646
  fieldName: "icon",
652
647
  fileName: basename(opts.file),
@@ -663,9 +658,7 @@ export function registerRooms(program) {
663
658
  .requiredOption("--room <roomId>", "target room id")
664
659
  .requiredOption("--file <path>", "local image file (png/jpg/jpeg/gif/webp, ≤10MB)")
665
660
  .action(async (opts) => {
666
- const { as } = program.opts();
667
- if (!as)
668
- throw new Error("--as <userId> is required");
661
+ const as = actingUserId(program);
669
662
  const ext = extname(opts.file).toLowerCase();
670
663
  const contentType = IMAGE_MIME[ext];
671
664
  if (!contentType) {
@@ -1,3 +1,4 @@
1
+ import { actingUserId } from "../auth.js";
1
2
  import { call } from "../client.js";
2
3
  import { getOrCreateGroup } from "./_group.js";
3
4
  const DEFAULT_LIMIT = 20;
@@ -58,9 +59,7 @@ export function registerUsers(program) {
58
59
  .option("--account-type <type>", "internal filter: all, authenticated, anonymous")
59
60
  .option("--authenticated", "shortcut for --account-type authenticated")
60
61
  .action(async (opts) => {
61
- const { as } = program.opts();
62
- if (!as)
63
- throw new Error("--as <userId> is required");
62
+ const as = actingUserId(program);
64
63
  const limit = parseLimit(opts.limit);
65
64
  if (opts.authenticated && opts.accountType) {
66
65
  throw new Error("Use either --authenticated or --account-type, not both");
@@ -94,9 +93,7 @@ export function registerUsers(program) {
94
93
  .requiredOption("--tier <tier>", `plan tier: ${Array.from(PLAN_TIERS).join(", ")}`)
95
94
  .option("--platform <platform>", `subscription platform: ${Array.from(PLAN_PLATFORMS).join(", ")}`)
96
95
  .action(async (opts) => {
97
- const { as } = program.opts();
98
- if (!as)
99
- throw new Error("--as <userId> is required");
96
+ const as = actingUserId(program);
100
97
  const data = await setPlanOverride({
101
98
  as,
102
99
  user: opts.user,
@@ -111,9 +108,7 @@ export function registerUsers(program) {
111
108
  .requiredOption("--user <userId>", "target user id")
112
109
  .option("--platform <platform>", `subscription platform: ${Array.from(PLAN_PLATFORMS).join(", ")}`)
113
110
  .action(async (opts) => {
114
- const { as } = program.opts();
115
- if (!as)
116
- throw new Error("--as <userId> is required");
111
+ const as = actingUserId(program);
117
112
  const data = await setPlanOverride({
118
113
  as,
119
114
  user: opts.user,
@@ -1,15 +1,32 @@
1
- import { mintToken } from "../auth.js";
1
+ import { actingUserId, decodeJwtPayload, resolveAuth } from "../auth.js";
2
+ function payloadUserId(payload) {
3
+ for (const key of ["userId", "id", "sub"]) {
4
+ const v = payload?.[key];
5
+ if (typeof v === "string" && v)
6
+ return v;
7
+ }
8
+ return undefined;
9
+ }
2
10
  export function registerWhoami(program) {
3
11
  program
4
12
  .command("whoami")
5
- .description("print the acting userId and a freshly minted JWT")
13
+ .description("print the active auth mode and the userId it acts as")
6
14
  .action(() => {
7
- const { as } = program.opts();
8
- if (!as) {
9
- throw new Error("--as <userId> is required");
15
+ const auth = resolveAuth(actingUserId(program));
16
+ if (auth.mode === "minted") {
17
+ const out = { mode: "minted", userId: auth.userId, source: "WORKCORD_JWT_SECRET" };
18
+ process.stdout.write(JSON.stringify(out) + "\n");
19
+ return;
10
20
  }
11
- const token = mintToken(as);
12
- process.stdout.write(JSON.stringify({ userId: as, token }) + "\n");
21
+ const payload = decodeJwtPayload(auth.token);
22
+ const out = {
23
+ mode: "token",
24
+ userId: payloadUserId(payload) ?? null,
25
+ source: "WORKCORD_TOKEN",
26
+ };
27
+ if (typeof payload?.exp === "number")
28
+ out.expiresAt = new Date(payload.exp * 1000).toISOString();
29
+ process.stdout.write(JSON.stringify(out) + "\n");
13
30
  });
14
31
  }
15
32
  //# sourceMappingURL=whoami.js.map
package/dist/config.js ADDED
@@ -0,0 +1,34 @@
1
+ import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ export const DEFAULT_BASE_URL = "https://work-rooms-api.wizeup.app";
5
+ const configPath = join(homedir(), ".workcord", "config.json");
6
+ export async function readConfig() {
7
+ try {
8
+ const value = JSON.parse(await readFile(configPath, "utf8"));
9
+ if (!value || typeof value !== "object")
10
+ return {};
11
+ const config = value;
12
+ return {
13
+ baseUrl: typeof config.baseUrl === "string" ? config.baseUrl : undefined,
14
+ token: typeof config.token === "string" ? config.token : undefined,
15
+ };
16
+ }
17
+ catch (err) {
18
+ if (err.code === "ENOENT")
19
+ return {};
20
+ throw new Error(`Could not read ${configPath}: ${err.message}`);
21
+ }
22
+ }
23
+ export async function saveConfig(update) {
24
+ const current = await readConfig();
25
+ const next = { ...current, ...update };
26
+ await mkdir(dirname(configPath), { recursive: true, mode: 0o700 });
27
+ await chmod(dirname(configPath), 0o700);
28
+ await writeFile(configPath, JSON.stringify(next, null, 2) + "\n", { mode: 0o600 });
29
+ await chmod(configPath, 0o600);
30
+ }
31
+ export function getConfigPath() {
32
+ return configPath;
33
+ }
34
+ //# sourceMappingURL=config.js.map
@@ -1,4 +1,5 @@
1
1
  import { call } from "../../client.js";
2
+ import { actingUserId } from "../../auth.js";
2
3
  import { getOrCreateGroup, hasSubcommand } from "../_helpers.js";
3
4
  export function register(program) {
4
5
  const group = getOrCreateGroup(program, "activity", "Activity operations");
@@ -8,9 +9,7 @@ export function register(program) {
8
9
  .description("GET /api/v1/users/me/activity/daily")
9
10
  .option("--period <value>", "string")
10
11
  .action(async (opts) => {
11
- const { as } = program.opts();
12
- if (!as)
13
- throw new Error("--as <userId> is required");
12
+ const as = actingUserId(program);
14
13
  const path = `/api/v1/users/me/activity/daily`;
15
14
  const query = {};
16
15
  {
@@ -28,9 +27,7 @@ export function register(program) {
28
27
  .description("GET /api/v1/users/me/activity/by-room")
29
28
  .option("--period <value>", "string")
30
29
  .action(async (opts) => {
31
- const { as } = program.opts();
32
- if (!as)
33
- throw new Error("--as <userId> is required");
30
+ const as = actingUserId(program);
34
31
  const path = `/api/v1/users/me/activity/by-room`;
35
32
  const query = {};
36
33
  {
@@ -1,4 +1,5 @@
1
1
  import { call } from "../../client.js";
2
+ import { actingUserId } from "../../auth.js";
2
3
  import { getOrCreateGroup, hasSubcommand } from "../_helpers.js";
3
4
  export function register(program) {
4
5
  const group = getOrCreateGroup(program, "ai", "AI operations");
@@ -9,9 +10,7 @@ export function register(program) {
9
10
  .requiredOption("--room-id <value>", "roomId (path param)")
10
11
  .requiredOption("--query <value>", "string, ≤500 chars")
11
12
  .action(async (opts) => {
12
- const { as } = program.opts();
13
- if (!as)
14
- throw new Error("--as <userId> is required");
13
+ const as = actingUserId(program);
15
14
  const path = `/api/v1/rooms/${encodeURIComponent(opts.roomId)}/ai/ask`;
16
15
  const body = {};
17
16
  {
@@ -28,9 +27,7 @@ export function register(program) {
28
27
  .command("marketplace")
29
28
  .description("GET /api/v1/ai/agents/marketplace")
30
29
  .action(async (opts) => {
31
- const { as } = program.opts();
32
- if (!as)
33
- throw new Error("--as <userId> is required");
30
+ const as = actingUserId(program);
34
31
  const path = `/api/v1/ai/agents/marketplace`;
35
32
  const data = await call({ method: "GET", path, asUserId: as });
36
33
  process.stdout.write(JSON.stringify(data) + "\n");
@@ -1,4 +1,5 @@
1
1
  import { call } from "../../client.js";
2
+ import { actingUserId } from "../../auth.js";
2
3
  import { getOrCreateGroup, hasSubcommand } from "../_helpers.js";
3
4
  export function register(program) {
4
5
  const group = getOrCreateGroup(program, "ambassador", "Ambassador operations");
@@ -7,9 +8,7 @@ export function register(program) {
7
8
  .command("get")
8
9
  .description("GET /api/v1/users/me/ambassador")
9
10
  .action(async (opts) => {
10
- const { as } = program.opts();
11
- if (!as)
12
- throw new Error("--as <userId> is required");
11
+ const as = actingUserId(program);
13
12
  const path = `/api/v1/users/me/ambassador`;
14
13
  const data = await call({ method: "GET", path, asUserId: as });
15
14
  process.stdout.write(JSON.stringify(data) + "\n");
@@ -21,9 +20,7 @@ export function register(program) {
21
20
  .description("POST /api/v1/users/me/ambassador")
22
21
  .option("--body <json>", "request body as JSON (no schema available)")
23
22
  .action(async (opts) => {
24
- const { as } = program.opts();
25
- if (!as)
26
- throw new Error("--as <userId> is required");
23
+ const as = actingUserId(program);
27
24
  const path = `/api/v1/users/me/ambassador`;
28
25
  const body = opts.body ? JSON.parse(opts.body) : undefined;
29
26
  const data = await call({ method: "POST", path, asUserId: as, body });
@@ -1,4 +1,5 @@
1
1
  import { call } from "../../client.js";
2
+ import { actingUserId } from "../../auth.js";
2
3
  import { getOrCreateGroup, hasSubcommand } from "../_helpers.js";
3
4
  export function register(program) {
4
5
  const group = getOrCreateGroup(program, "apple-iap", "AppleIap operations");
@@ -8,9 +9,7 @@ export function register(program) {
8
9
  .description("POST /api/v1/subscriptions/apple/verify")
9
10
  .requiredOption("--signed-transaction-jws <value>", "string")
10
11
  .action(async (opts) => {
11
- const { as } = program.opts();
12
- if (!as)
13
- throw new Error("--as <userId> is required");
12
+ const as = actingUserId(program);
14
13
  const path = `/api/v1/subscriptions/apple/verify`;
15
14
  const body = {};
16
15
  {
@@ -28,9 +27,7 @@ export function register(program) {
28
27
  .description("POST /api/v1/subscriptions/apple/restore")
29
28
  .requiredOption("--signed-transaction-jws <value>", "string")
30
29
  .action(async (opts) => {
31
- const { as } = program.opts();
32
- if (!as)
33
- throw new Error("--as <userId> is required");
30
+ const as = actingUserId(program);
34
31
  const path = `/api/v1/subscriptions/apple/restore`;
35
32
  const body = {};
36
33
  {
@@ -48,9 +45,7 @@ export function register(program) {
48
45
  .description("POST /api/v1/webhooks/apple")
49
46
  .option("--body <json>", "request body as JSON (no schema available)")
50
47
  .action(async (opts) => {
51
- const { as } = program.opts();
52
- if (!as)
53
- throw new Error("--as <userId> is required");
48
+ const as = actingUserId(program);
54
49
  const path = `/api/v1/webhooks/apple`;
55
50
  const body = opts.body ? JSON.parse(opts.body) : undefined;
56
51
  const data = await call({ method: "POST", path, asUserId: as, body });
@@ -1,4 +1,5 @@
1
1
  import { call } from "../../client.js";
2
+ import { actingUserId } from "../../auth.js";
2
3
  import { getOrCreateGroup, hasSubcommand } from "../_helpers.js";
3
4
  export function register(program) {
4
5
  const group = getOrCreateGroup(program, "attribution", "Attribution operations");
@@ -10,9 +11,7 @@ export function register(program) {
10
11
  .requiredOption("--device-id <value>", "string")
11
12
  .requiredOption("--platform <value>", "string")
12
13
  .action(async (opts) => {
13
- const { as } = program.opts();
14
- if (!as)
15
- throw new Error("--as <userId> is required");
14
+ const as = actingUserId(program);
16
15
  const path = `/api/v1/attribution/rooms-install`;
17
16
  const body = {};
18
17
  {
@@ -44,9 +43,7 @@ export function register(program) {
44
43
  .requiredOption("--device-id <value>", "string")
45
44
  .requiredOption("--hmac <value>", "string")
46
45
  .action(async (opts) => {
47
- const { as } = program.opts();
48
- if (!as)
49
- throw new Error("--as <userId> is required");
46
+ const as = actingUserId(program);
50
47
  const path = `/api/v1/attribution/install`;
51
48
  const body = {};
52
49
  {
@@ -83,9 +80,7 @@ export function register(program) {
83
80
  .command("pending-attribution")
84
81
  .description("GET /api/v1/attribution/pending")
85
82
  .action(async (opts) => {
86
- const { as } = program.opts();
87
- if (!as)
88
- throw new Error("--as <userId> is required");
83
+ const as = actingUserId(program);
89
84
  const path = `/api/v1/attribution/pending`;
90
85
  const data = await call({ method: "GET", path, asUserId: as });
91
86
  process.stdout.write(JSON.stringify(data) + "\n");
@@ -97,9 +92,7 @@ export function register(program) {
97
92
  .description("GET /api/v1/attribution/ios-pending")
98
93
  .requiredOption("--bundle_id <value>", "string")
99
94
  .action(async (opts) => {
100
- const { as } = program.opts();
101
- if (!as)
102
- throw new Error("--as <userId> is required");
95
+ const as = actingUserId(program);
103
96
  const path = `/api/v1/attribution/ios-pending`;
104
97
  const query = {};
105
98
  {
@@ -117,9 +110,7 @@ export function register(program) {
117
110
  .description("POST /api/v1/attribution/branch-webhook")
118
111
  .option("--body <json>", "request body as JSON (no schema available)")
119
112
  .action(async (opts) => {
120
- const { as } = program.opts();
121
- if (!as)
122
- throw new Error("--as <userId> is required");
113
+ const as = actingUserId(program);
123
114
  const path = `/api/v1/attribution/branch-webhook`;
124
115
  const body = opts.body ? JSON.parse(opts.body) : undefined;
125
116
  const data = await call({ method: "POST", path, asUserId: as, body });