@leemour/max-cli 0.1.0 → 0.2.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.
Files changed (78) hide show
  1. package/README.md +25 -9
  2. package/dist/cache/schema.d.ts +10 -1
  3. package/dist/cache/schema.d.ts.map +1 -1
  4. package/dist/cache/schema.js +71 -7
  5. package/dist/cache/schema.js.map +1 -1
  6. package/dist/cache/store.d.ts +84 -3
  7. package/dist/cache/store.d.ts.map +1 -1
  8. package/dist/cache/store.js +155 -25
  9. package/dist/cache/store.js.map +1 -1
  10. package/dist/client.d.ts +68 -9
  11. package/dist/client.d.ts.map +1 -1
  12. package/dist/client.js +286 -31
  13. package/dist/client.js.map +1 -1
  14. package/dist/commands/chats.d.ts.map +1 -1
  15. package/dist/commands/chats.js +5 -9
  16. package/dist/commands/chats.js.map +1 -1
  17. package/dist/commands/contacts.d.ts.map +1 -1
  18. package/dist/commands/contacts.js +46 -5
  19. package/dist/commands/contacts.js.map +1 -1
  20. package/dist/commands/login.d.ts +15 -0
  21. package/dist/commands/login.d.ts.map +1 -0
  22. package/dist/commands/login.js +43 -0
  23. package/dist/commands/login.js.map +1 -0
  24. package/dist/commands/logout.d.ts +10 -0
  25. package/dist/commands/logout.d.ts.map +1 -0
  26. package/dist/commands/logout.js +22 -0
  27. package/dist/commands/logout.js.map +1 -0
  28. package/dist/commands/me.d.ts +3 -0
  29. package/dist/commands/me.d.ts.map +1 -0
  30. package/dist/commands/me.js +18 -0
  31. package/dist/commands/me.js.map +1 -0
  32. package/dist/commands/messages.d.ts.map +1 -1
  33. package/dist/commands/messages.js +18 -3
  34. package/dist/commands/messages.js.map +1 -1
  35. package/dist/commands/paging.d.ts +38 -0
  36. package/dist/commands/paging.d.ts.map +1 -0
  37. package/dist/commands/paging.js +43 -0
  38. package/dist/commands/paging.js.map +1 -0
  39. package/dist/commands/send.d.ts +10 -0
  40. package/dist/commands/send.d.ts.map +1 -0
  41. package/dist/commands/send.js +30 -0
  42. package/dist/commands/send.js.map +1 -0
  43. package/dist/commands/session.d.ts.map +1 -1
  44. package/dist/commands/session.js +3 -3
  45. package/dist/commands/session.js.map +1 -1
  46. package/dist/config.d.ts +6 -0
  47. package/dist/config.d.ts.map +1 -1
  48. package/dist/config.js +10 -0
  49. package/dist/config.js.map +1 -1
  50. package/dist/domain/map.d.ts +1 -0
  51. package/dist/domain/map.d.ts.map +1 -1
  52. package/dist/domain/map.js +2 -0
  53. package/dist/domain/map.js.map +1 -1
  54. package/dist/domain/models.d.ts +18 -0
  55. package/dist/domain/models.d.ts.map +1 -1
  56. package/dist/generated/operations.generated.d.ts +1 -0
  57. package/dist/generated/operations.generated.d.ts.map +1 -1
  58. package/dist/protocol/session.d.ts +54 -0
  59. package/dist/protocol/session.d.ts.map +1 -0
  60. package/dist/protocol/session.js +57 -0
  61. package/dist/protocol/session.js.map +1 -0
  62. package/dist/session/adopt.d.ts +22 -0
  63. package/dist/session/adopt.d.ts.map +1 -0
  64. package/dist/session/adopt.js +29 -0
  65. package/dist/session/adopt.js.map +1 -0
  66. package/dist/session/handshake.d.ts +14 -1
  67. package/dist/session/handshake.d.ts.map +1 -1
  68. package/dist/session/handshake.js +5 -5
  69. package/dist/session/handshake.js.map +1 -1
  70. package/dist/spec/operations/auth.d.ts +42 -0
  71. package/dist/spec/operations/auth.d.ts.map +1 -0
  72. package/dist/spec/operations/session.d.ts +16 -0
  73. package/dist/spec/operations/session.d.ts.map +1 -1
  74. package/dist/spec/operations/session.js +21 -1
  75. package/dist/spec/operations/session.js.map +1 -1
  76. package/dist/version.d.ts +1 -1
  77. package/dist/version.js +1 -1
  78. package/package.json +4 -3
@@ -1,21 +1,17 @@
1
1
  import { Command } from "commander";
2
2
  import { openProfileCache } from "../cache/index.js";
3
3
  import { forCommand } from "./context.js";
4
+ import { renderPage, window, withPaging } from "./paging.js";
4
5
  export const chatsCommand = () => {
5
6
  const command = new Command("chats").description("the chats this account is in");
6
- command
7
- .command("list")
8
- .description("the chats this account is in")
9
- // No default on the option: with one, the flag is always set and a configured `limit` could
10
- // never win it. The number lives once, in `resolveSettings`.
11
- .option("--limit <n>", "how many to show", (value) => Number.parseInt(value, 10))
12
- .action(async function () {
13
- const { renderer, settings, createClient, run } = forCommand(this.optsWithGlobals());
7
+ withPaging(command.command("list").description("the chats this account is in")).action(async function () {
8
+ const context = forCommand(this.optsWithGlobals());
9
+ const { renderer, settings, createClient, run } = context;
14
10
  const cache = await openProfileCache(settings.profile, { onProblem: (message) => renderer.note(message) });
15
11
  await run("chats list", async (events) => {
16
12
  const client = createClient({ events, ...(cache ? { cache } : {}) });
17
13
  try {
18
- renderer.result(await client.chats.list(settings.limit));
14
+ renderPage(context, await client.chats.list(window(settings)));
19
15
  }
20
16
  finally {
21
17
  await client.close();
@@ -1 +1 @@
1
- {"version":3,"file":"chats.js","sourceRoot":"","sources":["../../src/commands/chats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEzC,MAAM,CAAC,MAAM,YAAY,GAAG,GAAY,EAAE;IACxC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,8BAA8B,CAAC,CAAA;IAEhF,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,8BAA8B,CAAC;QAC5C,4FAA4F;QAC5F,6DAA6D;SAC5D,MAAM,CAAC,aAAa,EAAE,kBAAkB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;SAChF,MAAM,CAAC,KAAK;QACX,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAA;QACpF,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAE1G,MAAM,GAAG,CAAC,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YACvC,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;YAEpE,IAAI,CAAC;gBACH,QAAQ,CAAC,MAAM,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;YAC1D,CAAC;oBAAS,CAAC;gBACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;gBACpB,KAAK,EAAE,KAAK,EAAE,CAAA;YAChB,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEJ,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
1
+ {"version":3,"file":"chats.js","sourceRoot":"","sources":["../../src/commands/chats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE5D,MAAM,CAAC,MAAM,YAAY,GAAG,GAAY,EAAE;IACxC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,8BAA8B,CAAC,CAAA;IAEhF,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,8BAA8B,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK;QAG1F,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAA;QAClD,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,OAAO,CAAA;QACzD,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAE1G,MAAM,GAAG,CAAC,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YACvC,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;YAEpE,IAAI,CAAC;gBACH,UAAU,CAAC,OAAO,EAAE,MAAM,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;YAChE,CAAC;oBAAS,CAAC;gBACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;gBACpB,KAAK,EAAE,KAAK,EAAE,CAAA;YAChB,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"contacts.d.ts","sourceRoot":"","sources":["../../src/commands/contacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAInC;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,QAAO,OAwBlC,CAAA"}
1
+ {"version":3,"file":"contacts.d.ts","sourceRoot":"","sources":["../../src/commands/contacts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAMnC;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,QAAO,OAuDlC,CAAA"}
@@ -1,6 +1,8 @@
1
+ import { CliError } from "@leemour/cli-core";
1
2
  import { Command } from "commander";
2
3
  import { openProfileCache } from "../cache/index.js";
3
4
  import { forCommand } from "./context.js";
5
+ import { renderPage, window, withPaging } from "./paging.js";
4
6
  /**
5
7
  * The people this account has a one-to-one chat with.
6
8
  *
@@ -10,17 +12,45 @@ import { forCommand } from "./context.js";
10
12
  */
11
13
  export const contactsCommand = () => {
12
14
  const command = new Command("contacts").description("people you have a one-to-one chat with");
15
+ withPaging(command.command("list").description("people you have a one-to-one chat with"))
16
+ .option("--order <recent|name>", "newest conversation first, or alphabetical")
17
+ .action(async function () {
18
+ const options = this.optsWithGlobals();
19
+ const context = forCommand(options);
20
+ const { renderer, settings, createClient, run } = context;
21
+ const cache = await openProfileCache(settings.profile, { onProblem: (message) => renderer.note(message) });
22
+ const order = orderFrom(options.order);
23
+ await run("contacts list", async (events) => {
24
+ const client = createClient({ events, ...(cache ? { cache } : {}) });
25
+ try {
26
+ renderPage(context, await client.contacts.list({ order, ...window(settings) }));
27
+ }
28
+ finally {
29
+ await client.close();
30
+ cache?.close();
31
+ }
32
+ });
33
+ });
34
+ /**
35
+ * The repair tool of the contact store, and **not how contacts normally arrive**: every command
36
+ * logs in, and every login carries the delta, so the store is already current. This is for a
37
+ * store that has drifted, or one a schema rebuild emptied.
38
+ *
39
+ * ⚠ **The summary is counts.** No name, no username, no description, no phone number — a person
40
+ * in a diagnostic is the one leak this project's sixth constraint is about.
41
+ */
13
42
  command
14
- .command("list")
15
- .description("people you have a one-to-one chat with")
16
- .option("--limit <n>", "how many to show", (value) => Number.parseInt(value, 10))
43
+ .command("sync")
44
+ .description("forget where the last sync left off and take the whole list again")
17
45
  .action(async function () {
18
46
  const { renderer, settings, createClient, run } = forCommand(this.optsWithGlobals());
19
47
  const cache = await openProfileCache(settings.profile, { onProblem: (message) => renderer.note(message) });
20
- await run("contacts list", async (events) => {
48
+ await run("contacts sync", async (events) => {
21
49
  const client = createClient({ events, ...(cache ? { cache } : {}) });
22
50
  try {
23
- renderer.result((await client.contacts.list()).slice(0, settings.limit));
51
+ const summary = await client.contacts.sync();
52
+ renderer.result(summary);
53
+ renderer.success(`${summary.added} new, ${summary.changed} changed, ${summary.known} people known`);
24
54
  }
25
55
  finally {
26
56
  await client.close();
@@ -30,4 +60,15 @@ export const contactsCommand = () => {
30
60
  });
31
61
  return command;
32
62
  };
63
+ /**
64
+ * ⚠ **A flag and no configuration field**, deliberately. `--order` and a `contactOrder` setting
65
+ * would be two spellings of one thing, which is what `--profile` was deleted for.
66
+ */
67
+ const orderFrom = (value) => {
68
+ if (value === undefined)
69
+ return "recent";
70
+ if (value === "recent" || value === "name")
71
+ return value;
72
+ throw new CliError("validation_error", `--order takes "recent" or "name", not "${String(value)}"`);
73
+ };
33
74
  //# sourceMappingURL=contacts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"contacts.js","sourceRoot":"","sources":["../../src/commands/contacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEzC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,GAAY,EAAE;IAC3C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,wCAAwC,CAAC,CAAA;IAE7F,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,wCAAwC,CAAC;SACrD,MAAM,CAAC,aAAa,EAAE,kBAAkB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;SAChF,MAAM,CAAC,KAAK;QACX,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAA;QACpF,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAE1G,MAAM,GAAG,CAAC,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAC1C,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;YAEpE,IAAI,CAAC;gBACH,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;YAC1E,CAAC;oBAAS,CAAC;gBACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;gBACpB,KAAK,EAAE,KAAK,EAAE,CAAA;YAChB,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEJ,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
1
+ {"version":3,"file":"contacts.js","sourceRoot":"","sources":["../../src/commands/contacts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { Command } from "commander";
2
+ /**
3
+ * For now, importing a token obtained elsewhere — from `web.max.ru`, or from another client.
4
+ *
5
+ * This is not a stopgap: it is the escape hatch that keeps every other command usable when our own
6
+ * login flow meets a captcha or an unusual second factor, and it is how the slice is tested
7
+ * without an SMS per run. The interactive phone-and-code flow lands beside it, not instead of it.
8
+ *
9
+ * **The token is asked for, not passed.** `--token` puts it in `ps` output and shell history, and a
10
+ * file leaves a copy nobody deletes, so with neither given it is read from the terminal without
11
+ * being echoed — or from a pipe, for `pass show max | max login`. From there it goes to the OS
12
+ * keyring and nowhere else.
13
+ */
14
+ export declare const loginCommand: () => Command;
15
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAMnC;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,QAAO,OA2B1B,CAAA"}
@@ -0,0 +1,43 @@
1
+ import { Command } from "commander";
2
+ import { MaxClient } from "../client.js";
3
+ import { resolveOutput } from "../output.js";
4
+ import { readSecret } from "../session/prompt.js";
5
+ import { SessionStore } from "../session/store.js";
6
+ /**
7
+ * For now, importing a token obtained elsewhere — from `web.max.ru`, or from another client.
8
+ *
9
+ * This is not a stopgap: it is the escape hatch that keeps every other command usable when our own
10
+ * login flow meets a captcha or an unusual second factor, and it is how the slice is tested
11
+ * without an SMS per run. The interactive phone-and-code flow lands beside it, not instead of it.
12
+ *
13
+ * **The token is asked for, not passed.** `--token` puts it in `ps` output and shell history, and a
14
+ * file leaves a copy nobody deletes, so with neither given it is read from the terminal without
15
+ * being echoed — or from a pipe, for `pass show max | max login`. From there it goes to the OS
16
+ * keyring and nowhere else.
17
+ */
18
+ export const loginCommand = () => new Command("login")
19
+ .description("store a MAX session for this profile")
20
+ .option("--token <token>", "a session token; prompted for, or read from a pipe, when omitted")
21
+ .action(async function () {
22
+ const options = this.optsWithGlobals();
23
+ const { renderer } = resolveOutput(options);
24
+ const token = options.token ?? process.env.MAX_TOKEN?.trim() ?? (await readSecret("MAX token: "));
25
+ if (!token) {
26
+ renderer.failure("no token given");
27
+ process.exitCode = 2;
28
+ return;
29
+ }
30
+ const store = new SessionStore({ profile: options.profile });
31
+ store.writeToken(token);
32
+ const client = new MaxClient({ store });
33
+ try {
34
+ await client.connect();
35
+ const profile = client.account.me();
36
+ renderer.result({ profile, stored: true });
37
+ renderer.success(`logged in as ${profile.name ?? profile.id}`);
38
+ }
39
+ finally {
40
+ await client.close();
41
+ }
42
+ });
43
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAElD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,GAAY,EAAE,CACxC,IAAI,OAAO,CAAC,OAAO,CAAC;KACjB,WAAW,CAAC,sCAAsC,CAAC;KACnD,MAAM,CAAC,iBAAiB,EAAE,kEAAkE,CAAC;KAC7F,MAAM,CAAC,KAAK;IACX,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,CAAA;IACtC,MAAM,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;IAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,UAAU,CAAC,aAAa,CAAC,CAAC,CAAA;IAEjG,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,QAAQ,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAA;QAClC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;QACpB,OAAM;IACR,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;IAC5D,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;IAEvB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;IACvC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,EAAE,CAAA;QACtB,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,CAAA;QACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;QAC1C,QAAQ,CAAC,OAAO,CAAC,gBAAgB,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC,CAAA;IAChE,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;IACtB,CAAC;AACH,CAAC,CAAC,CAAA"}
@@ -0,0 +1,10 @@
1
+ import { Command } from "commander";
2
+ /**
3
+ * Local only, for now: it forgets the token and the device identity on this machine.
4
+ *
5
+ * It does **not** yet send LOGOUT (opcode 20), which would end the session on MAX's side too. That
6
+ * distinction is in the output rather than glossed over: a forgotten token that is still live
7
+ * elsewhere is a different thing from a revoked one.
8
+ */
9
+ export declare const logoutCommand: () => Command;
10
+ //# sourceMappingURL=logout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAInC;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,QAAO,OAU7B,CAAA"}
@@ -0,0 +1,22 @@
1
+ import { Command } from "commander";
2
+ import { resolveOutput } from "../output.js";
3
+ import { SessionStore } from "../session/store.js";
4
+ /**
5
+ * Local only, for now: it forgets the token and the device identity on this machine.
6
+ *
7
+ * It does **not** yet send LOGOUT (opcode 20), which would end the session on MAX's side too. That
8
+ * distinction is in the output rather than glossed over: a forgotten token that is still live
9
+ * elsewhere is a different thing from a revoked one.
10
+ */
11
+ export const logoutCommand = () => new Command("logout").description("forget the stored session for this profile").action(function () {
12
+ const options = this.optsWithGlobals();
13
+ const { renderer } = resolveOutput(options);
14
+ const store = new SessionStore({ profile: options.profile });
15
+ const had = store.forget();
16
+ renderer.result({ profile: store.profile, forgotten: had, revokedOnServer: false });
17
+ if (had)
18
+ renderer.success(`forgot the session for "${store.profile}" on this machine`);
19
+ else
20
+ renderer.note(`there was no session for "${store.profile}"`);
21
+ });
22
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAElD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAY,EAAE,CACzC,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,4CAA4C,CAAC,CAAC,MAAM,CAAC;IACrF,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,CAAA;IACtC,MAAM,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;IAC3C,MAAM,KAAK,GAAG,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;IAC5D,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,EAAE,CAAA;IAE1B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAA;IACnF,IAAI,GAAG;QAAE,QAAQ,CAAC,OAAO,CAAC,2BAA2B,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;;QACjF,QAAQ,CAAC,IAAI,CAAC,6BAA6B,KAAK,CAAC,OAAO,GAAG,CAAC,CAAA;AACnE,CAAC,CAAC,CAAA"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const meCommand: () => Command;
3
+ //# sourceMappingURL=me.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"me.d.ts","sourceRoot":"","sources":["../../src/commands/me.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAKnC,eAAO,MAAM,SAAS,QAAO,OAazB,CAAA"}
@@ -0,0 +1,18 @@
1
+ import { Command } from "commander";
2
+ import { MaxClient } from "../client.js";
3
+ import { resolveOutput } from "../output.js";
4
+ import { SessionStore } from "../session/store.js";
5
+ export const meCommand = () => new Command("me").description("who this profile is logged in as").action(async function () {
6
+ const options = this.optsWithGlobals();
7
+ const { renderer } = resolveOutput(options);
8
+ const client = new MaxClient({ store: new SessionStore({ profile: options.profile }) });
9
+ try {
10
+ await client.connect();
11
+ renderer.result(client.account.me());
12
+ }
13
+ finally {
14
+ // Nothing below this line: an open socket keeps the process alive after the answer printed.
15
+ await client.close();
16
+ }
17
+ });
18
+ //# sourceMappingURL=me.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"me.js","sourceRoot":"","sources":["../../src/commands/me.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAElD,MAAM,CAAC,MAAM,SAAS,GAAG,GAAY,EAAE,CACrC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,kCAAkC,CAAC,CAAC,MAAM,CAAC,KAAK;IAC5E,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,CAAA;IACtC,MAAM,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;IAC3C,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAA;IAEvF,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,EAAE,CAAA;QACtB,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAA;IACtC,CAAC;YAAS,CAAC;QACT,4FAA4F;QAC5F,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;IACtB,CAAC;AACH,CAAC,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/commands/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAInC,eAAO,MAAM,eAAe,QAAO,OAgElC,CAAA"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/commands/messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAKnC,eAAO,MAAM,eAAe,QAAO,OA8ElC,CAAA"}
@@ -1,6 +1,7 @@
1
1
  import { Command } from "commander";
2
2
  import { openProfileCache } from "../cache/index.js";
3
3
  import { forCommand } from "./context.js";
4
+ import { renderPage } from "./paging.js";
4
5
  export const messagesCommand = () => {
5
6
  const command = new Command("messages").description("read and send messages in a chat");
6
7
  /**
@@ -12,14 +13,21 @@ export const messagesCommand = () => {
12
13
  .argument("<chat>", "chat id, or part of a chat name")
13
14
  .description("recent messages in a chat, oldest first")
14
15
  .option("--limit <n>", "how many to read", (value) => Number.parseInt(value, 10))
16
+ // Not `--page`: this history is anchored in time, so paging backwards through it is exact
17
+ // rather than approximate. A message id is what the reader has in front of them, having just
18
+ // read the output; an ISO 8601 time is what still works once that message is gone.
19
+ .option("--before <id-or-time>", "read what came before this message id, or this ISO 8601 time")
15
20
  .action(async function (chat) {
16
- const { renderer, settings, createClient, run } = forCommand(this.optsWithGlobals());
21
+ const options = this.optsWithGlobals();
22
+ const context = forCommand(options);
23
+ const { renderer, settings, createClient, run } = context;
17
24
  const cache = await openProfileCache(settings.profile, { onProblem: (message) => renderer.note(message) });
18
25
  await run("messages list", async (events) => {
19
26
  const client = createClient({ events, ...(cache ? { cache } : {}) });
20
27
  try {
21
28
  const chatId = await client.chats.resolve(chat);
22
- renderer.result(await client.messages.list(chatId, settings.limit));
29
+ const before = options.before === undefined ? {} : { before: client.messages.before(String(options.before)) };
30
+ renderPage(context, await client.messages.list(chatId, { limit: settings.limit, ...before }));
23
31
  }
24
32
  finally {
25
33
  await client.close();
@@ -40,6 +48,10 @@ export const messagesCommand = () => {
40
48
  .argument("<text>", "what to say")
41
49
  .description("send one text message")
42
50
  .option("--cid <n>", "reuse a client id from an earlier ambiguous send; MAX collapses the duplicate", (value) => Number.parseInt(value, 10))
51
+ // `notify` is part of MSG_SEND and has always been sent as `true`. It is the one send option
52
+ // whose absence is felt at the other end rather than here: a script posting at 3am wakes
53
+ // somebody up, and there was no way to say otherwise.
54
+ .option("--silent", "deliver without a notification")
43
55
  .action(async function (chat, text) {
44
56
  const options = this.optsWithGlobals();
45
57
  const { renderer, settings, createClient, run } = forCommand(options);
@@ -48,7 +60,10 @@ export const messagesCommand = () => {
48
60
  const client = createClient({ events, ...(cache ? { cache } : {}) });
49
61
  try {
50
62
  const chatId = await client.chats.resolve(chat);
51
- const sent = await client.messages.send(chatId, text, options.cid === undefined ? {} : { cid: options.cid });
63
+ const sent = await client.messages.send(chatId, text, {
64
+ ...(options.cid === undefined ? {} : { cid: options.cid }),
65
+ ...(options.silent === true ? { notify: false } : {}),
66
+ });
52
67
  renderer.result(sent);
53
68
  }
54
69
  finally {
@@ -1 +1 @@
1
- {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/commands/messages.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/commands/messages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { Renderer, RenderFormat } from "@leemour/cli-core";
2
+ import type { Command } from "commander";
3
+ import type { Settings } from "../config.js";
4
+ import type { Page } from "../domain/models.js";
5
+ /**
6
+ * The three flags every listing shares, so no command invents its own spelling of them.
7
+ *
8
+ * ⚠ **None of them gets a `default`.** With one, commander reports the flag as always given and a
9
+ * configured `limit` could never win it; the number lives once, in `resolveSettings`.
10
+ */
11
+ export declare const withPaging: (command: Command) => Command;
12
+ /**
13
+ * Which rows to ask the store for. `--all` means no limit, which the store reads as "everything".
14
+ *
15
+ * ⚠ **A page number over a live list can repeat or skip a row.** The order is most-recent-first,
16
+ * so a message arriving between page one and page two pushes somebody across the boundary. Every
17
+ * CLI that pages this way has this; it is in `--help` rather than engineered away.
18
+ */
19
+ export declare const window: ({ limit, page, all }: Settings) => {
20
+ limit?: number;
21
+ offset: number;
22
+ };
23
+ /**
24
+ * **One shape for every listing**, and the caller never has to work out which one it got.
25
+ *
26
+ * In the machine modes stdout carries the envelope. For a person it carries the table it always
27
+ * did, and the line about there being another page goes to **stderr** as a note — stdout is data
28
+ * in every mode, and a pager's hint is not data.
29
+ *
30
+ * It is a helper each command calls rather than something inside `renderer.result`, because
31
+ * `account show` and `session start` are not lists and keep answering a bare object.
32
+ */
33
+ export declare const renderPage: <T>({ renderer, format, settings }: {
34
+ renderer: Renderer;
35
+ format: RenderFormat;
36
+ settings: Settings;
37
+ }, { items, hasMore }: Page<T>) => void;
38
+ //# sourceMappingURL=paging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paging.d.ts","sourceRoot":"","sources":["../../src/commands/paging.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAE/C;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GAAI,SAAS,OAAO,KAAG,OAIF,CAAA;AAE5C;;;;;;GAMG;AACH,eAAO,MAAM,MAAM,GAAI,sBAAsB,QAAQ,KAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAC3B,CAAA;AAE7D;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,EAC1B,gCAAgC;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,YAAY,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,EAChG,oBAAoB,IAAI,CAAC,CAAC,CAAC,KAC1B,IAcF,CAAA"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The three flags every listing shares, so no command invents its own spelling of them.
3
+ *
4
+ * ⚠ **None of them gets a `default`.** With one, commander reports the flag as always given and a
5
+ * configured `limit` could never win it; the number lives once, in `resolveSettings`.
6
+ */
7
+ export const withPaging = (command) => command
8
+ .option("--limit <n>", "how many to show", (value) => Number.parseInt(value, 10))
9
+ .option("--page <n>", "which page, starting at 1", (value) => Number.parseInt(value, 10))
10
+ .option("--all", "every row, no paging");
11
+ /**
12
+ * Which rows to ask the store for. `--all` means no limit, which the store reads as "everything".
13
+ *
14
+ * ⚠ **A page number over a live list can repeat or skip a row.** The order is most-recent-first,
15
+ * so a message arriving between page one and page two pushes somebody across the boundary. Every
16
+ * CLI that pages this way has this; it is in `--help` rather than engineered away.
17
+ */
18
+ export const window = ({ limit, page, all }) => all ? { offset: 0 } : { limit, offset: (page - 1) * limit };
19
+ /**
20
+ * **One shape for every listing**, and the caller never has to work out which one it got.
21
+ *
22
+ * In the machine modes stdout carries the envelope. For a person it carries the table it always
23
+ * did, and the line about there being another page goes to **stderr** as a note — stdout is data
24
+ * in every mode, and a pager's hint is not data.
25
+ *
26
+ * It is a helper each command calls rather than something inside `renderer.result`, because
27
+ * `account show` and `session start` are not lists and keep answering a bare object.
28
+ */
29
+ export const renderPage = ({ renderer, format, settings }, { items, hasMore }) => {
30
+ if (format !== "pretty") {
31
+ renderer.result({
32
+ items,
33
+ page: settings.all ? 1 : settings.page,
34
+ limit: settings.all ? items.length : settings.limit,
35
+ hasMore: settings.all ? false : hasMore,
36
+ });
37
+ return;
38
+ }
39
+ renderer.result(items);
40
+ if (!settings.all && hasMore)
41
+ renderer.note(`page ${settings.page} of more — \`--page ${settings.page + 1}\` for the next`);
42
+ };
43
+ //# sourceMappingURL=paging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paging.js","sourceRoot":"","sources":["../../src/commands/paging.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,OAAgB,EAAW,EAAE,CACtD,OAAO;KACJ,MAAM,CAAC,aAAa,EAAE,kBAAkB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;KAChF,MAAM,CAAC,YAAY,EAAE,2BAA2B,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;KACxF,MAAM,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAA;AAE5C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAY,EAAsC,EAAE,CAC3F,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,EAAE,CAAA;AAE7D;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAoE,EAChG,EAAE,KAAK,EAAE,OAAO,EAAW,EACrB,EAAE;IACR,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,QAAQ,CAAC,MAAM,CAAC;YACd,KAAK;YACL,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI;YACtC,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK;YACnD,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO;SACxC,CAAC,CAAA;QACF,OAAM;IACR,CAAC;IAED,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACtB,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,OAAO;QAC1B,QAAQ,CAAC,IAAI,CAAC,QAAQ,QAAQ,CAAC,IAAI,uBAAuB,QAAQ,CAAC,IAAI,GAAG,CAAC,iBAAiB,CAAC,CAAA;AACjG,CAAC,CAAA"}
@@ -0,0 +1,10 @@
1
+ import { Command } from "commander";
2
+ /**
3
+ * One message, one command, no retry.
4
+ *
5
+ * There is no `--dry-run` here: the target and the text are both in the line the person typed, so
6
+ * a preview would restate the command back at them (REQUIREMENTS §21). What this command does owe
7
+ * the caller is honesty about an outcome it does not know — see `MaxClient.sendMessage`.
8
+ */
9
+ export declare const sendCommand: () => Command;
10
+ //# sourceMappingURL=send.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../src/commands/send.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAKnC;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,QAAO,OAoBzB,CAAA"}
@@ -0,0 +1,30 @@
1
+ import { Command } from "commander";
2
+ import { MaxClient } from "../client.js";
3
+ import { resolveOutput } from "../output.js";
4
+ import { SessionStore } from "../session/store.js";
5
+ /**
6
+ * One message, one command, no retry.
7
+ *
8
+ * There is no `--dry-run` here: the target and the text are both in the line the person typed, so
9
+ * a preview would restate the command back at them (REQUIREMENTS §21). What this command does owe
10
+ * the caller is honesty about an outcome it does not know — see `MaxClient.sendMessage`.
11
+ */
12
+ export const sendCommand = () => new Command("send")
13
+ .argument("<chat>", "chat id, or part of a chat name")
14
+ .argument("<text>", "what to say")
15
+ .description("send one text message")
16
+ .option("--cid <n>", "reuse a client id from an earlier ambiguous send; MAX collapses the duplicate", (value) => Number.parseInt(value, 10))
17
+ .action(async function (chat, text) {
18
+ const options = this.optsWithGlobals();
19
+ const { renderer } = resolveOutput(options);
20
+ const client = new MaxClient({ store: new SessionStore({ profile: options.profile }) });
21
+ try {
22
+ await client.connect();
23
+ const chatId = await client.chats.resolve(chat);
24
+ renderer.result(await client.messages.send(chatId, text, options.cid === undefined ? {} : { cid: options.cid }));
25
+ }
26
+ finally {
27
+ await client.close();
28
+ }
29
+ });
30
+ //# sourceMappingURL=send.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send.js","sourceRoot":"","sources":["../../src/commands/send.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAElD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAAY,EAAE,CACvC,IAAI,OAAO,CAAC,MAAM,CAAC;KAChB,QAAQ,CAAC,QAAQ,EAAE,iCAAiC,CAAC;KACrD,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;KACjC,WAAW,CAAC,uBAAuB,CAAC;KACpC,MAAM,CAAC,WAAW,EAAE,+EAA+E,EAAE,CAAC,KAAK,EAAE,EAAE,CAC9G,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAC3B;KACA,MAAM,CAAC,KAAK,WAA0B,IAAY,EAAE,IAAY;IAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,CAAA;IACtC,MAAM,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;IAC3C,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAA;IAEvF,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,EAAE,CAAA;QACtB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC/C,QAAQ,CAAC,MAAM,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;IAClH,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;IACtB,CAAC;AACH,CAAC,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/commands/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAKnC,eAAO,MAAM,cAAc,QAAO,OA4EjC,CAAA"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/commands/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAMnC,eAAO,MAAM,cAAc,QAAO,OA0EjC,CAAA"}
@@ -1,5 +1,6 @@
1
1
  import { Command } from "commander";
2
2
  import { commandWords, refuseCommandName, rootOf } from "../profile.js";
3
+ import { adoptToken } from "../session/adopt.js";
3
4
  import { readSecret } from "../session/prompt.js";
4
5
  import { forCommand } from "./context.js";
5
6
  export const sessionCommand = () => {
@@ -14,7 +15,7 @@ export const sessionCommand = () => {
14
15
  * **The token is asked for, not passed.** A token in argv is read by `ps` and kept by shell
15
16
  * history, and a file leaves a copy nobody deletes, so with `MAX_TOKEN` unset it is read from the
16
17
  * terminal without being echoed — or from a pipe, for `pass show max | max session start`. From
17
- * there it goes to the OS keyring.
18
+ * there it goes to the OS keyring — **but only once MAX has accepted it**, which is `adoptToken`.
18
19
  */
19
20
  command
20
21
  .command("start")
@@ -31,11 +32,10 @@ export const sessionCommand = () => {
31
32
  process.exitCode = 2;
32
33
  return;
33
34
  }
34
- store.writeToken(token);
35
35
  await run("session start", async (events) => {
36
36
  const client = createClient({ events });
37
37
  try {
38
- await client.connect();
38
+ await adoptToken(client, store, token);
39
39
  const profile = client.account.me();
40
40
  renderer.result({ profile, stored: true });
41
41
  renderer.success(`logged in as ${profile.name ?? profile.id}`);
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/commands/session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/commands/session.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -18,6 +18,8 @@ export interface GlobalFlags {
18
18
  quiet?: boolean;
19
19
  verbose?: boolean;
20
20
  limit?: number;
21
+ page?: number;
22
+ all?: boolean;
21
23
  record?: boolean;
22
24
  }
23
25
  export interface Settings {
@@ -28,6 +30,10 @@ export interface Settings {
28
30
  /** Unset means "decide from the terminal", which is `resolveOutput`'s job, not this one's. */
29
31
  color: boolean | undefined;
30
32
  limit: number;
33
+ /** Which page, 1-based. Per invocation only — a page number in a configuration file is a setting nobody wants twice. */
34
+ page: number;
35
+ /** Every row, no paging. Also per invocation only. */
36
+ all: boolean;
31
37
  /** Unset means the transport's own default; the number lives in `protocol/connection.ts`. */
32
38
  timeoutMs: number | undefined;
33
39
  record: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AA6B5B,eAAO,MAAM,YAAY;;;;;;QALvB,6EAA6E;;;;aAQ7E,CAAA;AAEF,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,YAAY,CAAC,CAAA;AAEvD,gGAAgG;AAChG,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,OAAO,CAAA;IACb,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;IAChB,8FAA8F;IAC9F,KAAK,EAAE,OAAO,GAAG,SAAS,CAAA;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,6FAA6F;IAC7F,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,MAAM,EAAE,OAAO,CAAA;IACf,eAAe,EAAE,MAAM,CAAA;IACvB,4FAA4F;IAC5F,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,GAAI,QAAO,WAAgB,EAAE,qBAAkC,cAAmB,aA4B7G,CAAA"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AA6B5B,eAAO,MAAM,YAAY;;;;;;QALvB,6EAA6E;;;;aAQ7E,CAAA;AAEF,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,YAAY,CAAC,CAAA;AAEvD,gGAAgG;AAChG,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,OAAO,CAAA;IACb,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;IAChB,8FAA8F;IAC9F,KAAK,EAAE,OAAO,GAAG,SAAS,CAAA;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,wHAAwH;IACxH,IAAI,EAAE,MAAM,CAAA;IACZ,sDAAsD;IACtD,GAAG,EAAE,OAAO,CAAA;IACZ,6FAA6F;IAC7F,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,MAAM,EAAE,OAAO,CAAA;IACf,eAAe,EAAE,MAAM,CAAA;IACvB,4FAA4F;IAC5F,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,GAAI,QAAO,WAAgB,EAAE,qBAAkC,cAAmB,aAwC7G,CAAA"}
package/dist/config.js CHANGED
@@ -50,6 +50,8 @@ export const resolveSettings = (flags = {}, { env = process.env, configDir } = {
50
50
  verbose: flags.verbose === true,
51
51
  color: configured.color,
52
52
  limit: flags.limit ?? configured.limit ?? DEFAULT_LIMIT,
53
+ page: flags.page ?? 1,
54
+ all: flags.all === true,
53
55
  timeoutMs: configured.timeoutMs,
54
56
  record: flags.record ?? configured.record ?? false,
55
57
  keepRunsForDays: configured.keepRunsForDays ?? DEFAULT_KEEP_RUNS_FOR_DAYS,
@@ -60,6 +62,14 @@ export const resolveSettings = (flags = {}, { env = process.env, configDir } = {
60
62
  if (!Number.isInteger(settings.limit) || settings.limit < 1) {
61
63
  throw new CliError("validation_error", `--limit takes a whole number from 1 upwards, not ${flags.limit}`);
62
64
  }
65
+ if (!Number.isInteger(settings.page) || settings.page < 1) {
66
+ throw new CliError("validation_error", `--page takes a whole number from 1 upwards, not ${flags.page}`);
67
+ }
68
+ // Refused rather than resolved: one of the two would silently win, and which one is exactly the
69
+ // sort of thing a caller discovers from a wrong answer rather than from a message.
70
+ if (settings.all && flags.page !== undefined) {
71
+ throw new CliError("validation_error", "--all and --page ask for different things; use one or the other");
72
+ }
63
73
  return settings;
64
74
  };
65
75
  /**