@leemour/max-cli 0.1.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.
- package/LICENSE +21 -0
- package/README.md +176 -0
- package/dist/bin/max.d.ts +3 -0
- package/dist/bin/max.d.ts.map +1 -0
- package/dist/bin/max.js +14 -0
- package/dist/bin/max.js.map +1 -0
- package/dist/cache/driver.d.ts +38 -0
- package/dist/cache/driver.d.ts.map +1 -0
- package/dist/cache/driver.js +26 -0
- package/dist/cache/driver.js.map +1 -0
- package/dist/cache/drivers/bun-sqlite.d.ts +8 -0
- package/dist/cache/drivers/bun-sqlite.d.ts.map +1 -0
- package/dist/cache/drivers/bun-sqlite.js +23 -0
- package/dist/cache/drivers/bun-sqlite.js.map +1 -0
- package/dist/cache/drivers/node-sqlite.d.ts +8 -0
- package/dist/cache/drivers/node-sqlite.d.ts.map +1 -0
- package/dist/cache/drivers/node-sqlite.js +22 -0
- package/dist/cache/drivers/node-sqlite.js.map +1 -0
- package/dist/cache/index.d.ts +22 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +33 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/open.d.ts +14 -0
- package/dist/cache/open.d.ts.map +1 -0
- package/dist/cache/open.js +26 -0
- package/dist/cache/open.js.map +1 -0
- package/dist/cache/schema.d.ts +14 -0
- package/dist/cache/schema.d.ts.map +1 -0
- package/dist/cache/schema.js +95 -0
- package/dist/cache/schema.js.map +1 -0
- package/dist/cache/store.d.ts +32 -0
- package/dist/cache/store.d.ts.map +1 -0
- package/dist/cache/store.js +153 -0
- package/dist/cache/store.js.map +1 -0
- package/dist/client.d.ts +103 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +383 -0
- package/dist/client.js.map +1 -0
- package/dist/commands/account.d.ts +3 -0
- package/dist/commands/account.d.ts.map +1 -0
- package/dist/commands/account.js +24 -0
- package/dist/commands/account.js.map +1 -0
- package/dist/commands/cache.d.ts +10 -0
- package/dist/commands/cache.d.ts.map +1 -0
- package/dist/commands/cache.js +36 -0
- package/dist/commands/cache.js.map +1 -0
- package/dist/commands/chats.d.ts +3 -0
- package/dist/commands/chats.d.ts.map +1 -0
- package/dist/commands/chats.js +28 -0
- package/dist/commands/chats.js.map +1 -0
- package/dist/commands/contacts.d.ts +10 -0
- package/dist/commands/contacts.d.ts.map +1 -0
- package/dist/commands/contacts.js +33 -0
- package/dist/commands/contacts.js.map +1 -0
- package/dist/commands/context.d.ts +34 -0
- package/dist/commands/context.d.ts.map +1 -0
- package/dist/commands/context.js +40 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/messages.d.ts +3 -0
- package/dist/commands/messages.d.ts.map +1 -0
- package/dist/commands/messages.js +62 -0
- package/dist/commands/messages.js.map +1 -0
- package/dist/commands/runs.d.ts +9 -0
- package/dist/commands/runs.d.ts.map +1 -0
- package/dist/commands/runs.js +68 -0
- package/dist/commands/runs.js.map +1 -0
- package/dist/commands/session.d.ts +3 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +74 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/config.d.ts +53 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +83 -0
- package/dist/config.js.map +1 -0
- package/dist/domain/map.d.ts +22 -0
- package/dist/domain/map.d.ts.map +1 -0
- package/dist/domain/map.js +107 -0
- package/dist/domain/map.js.map +1 -0
- package/dist/domain/models.d.ts +57 -0
- package/dist/domain/models.d.ts.map +1 -0
- package/dist/domain/models.js +7 -0
- package/dist/domain/models.js.map +1 -0
- package/dist/generated/client.generated.d.ts +30 -0
- package/dist/generated/client.generated.d.ts.map +1 -0
- package/dist/generated/client.generated.js +26 -0
- package/dist/generated/client.generated.js.map +1 -0
- package/dist/generated/opcodes.generated.d.ts +44 -0
- package/dist/generated/opcodes.generated.d.ts.map +1 -0
- package/dist/generated/opcodes.generated.js +44 -0
- package/dist/generated/opcodes.generated.js.map +1 -0
- package/dist/generated/operations.generated.d.ts +76 -0
- package/dist/generated/operations.generated.d.ts.map +1 -0
- package/dist/generated/operations.generated.js +15 -0
- package/dist/generated/operations.generated.js.map +1 -0
- package/dist/output.d.ts +22 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +34 -0
- package/dist/output.js.map +1 -0
- package/dist/profile.d.ts +33 -0
- package/dist/profile.d.ts.map +1 -0
- package/dist/profile.js +60 -0
- package/dist/profile.js.map +1 -0
- package/dist/program.d.ts +29 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +130 -0
- package/dist/program.js.map +1 -0
- package/dist/protocol/connection.d.ts +60 -0
- package/dist/protocol/connection.d.ts.map +1 -0
- package/dist/protocol/connection.js +142 -0
- package/dist/protocol/connection.js.map +1 -0
- package/dist/protocol/frame.d.ts +44 -0
- package/dist/protocol/frame.d.ts.map +1 -0
- package/dist/protocol/frame.js +68 -0
- package/dist/protocol/frame.js.map +1 -0
- package/dist/runs/events.d.ts +92 -0
- package/dist/runs/events.d.ts.map +1 -0
- package/dist/runs/events.js +85 -0
- package/dist/runs/events.js.map +1 -0
- package/dist/runs/recording.d.ts +35 -0
- package/dist/runs/recording.d.ts.map +1 -0
- package/dist/runs/recording.js +53 -0
- package/dist/runs/recording.js.map +1 -0
- package/dist/runs/run.d.ts +81 -0
- package/dist/runs/run.d.ts.map +1 -0
- package/dist/runs/run.js +175 -0
- package/dist/runs/run.js.map +1 -0
- package/dist/session/handshake.d.ts +26 -0
- package/dist/session/handshake.d.ts.map +1 -0
- package/dist/session/handshake.js +32 -0
- package/dist/session/handshake.js.map +1 -0
- package/dist/session/prompt.d.ts +18 -0
- package/dist/session/prompt.d.ts.map +1 -0
- package/dist/session/prompt.js +41 -0
- package/dist/session/prompt.js.map +1 -0
- package/dist/session/store.d.ts +46 -0
- package/dist/session/store.d.ts.map +1 -0
- package/dist/session/store.js +80 -0
- package/dist/session/store.js.map +1 -0
- package/dist/spec/check.d.ts +16 -0
- package/dist/spec/check.d.ts.map +1 -0
- package/dist/spec/check.js +44 -0
- package/dist/spec/check.js.map +1 -0
- package/dist/spec/define.d.ts +95 -0
- package/dist/spec/define.d.ts.map +1 -0
- package/dist/spec/define.js +34 -0
- package/dist/spec/define.js.map +1 -0
- package/dist/spec/identity.d.ts +23 -0
- package/dist/spec/identity.d.ts.map +1 -0
- package/dist/spec/identity.js +23 -0
- package/dist/spec/identity.js.map +1 -0
- package/dist/spec/index.d.ts +15 -0
- package/dist/spec/index.d.ts.map +1 -0
- package/dist/spec/index.js +30 -0
- package/dist/spec/index.js.map +1 -0
- package/dist/spec/operations/chats.d.ts +25 -0
- package/dist/spec/operations/chats.d.ts.map +1 -0
- package/dist/spec/operations/chats.js +49 -0
- package/dist/spec/operations/chats.js.map +1 -0
- package/dist/spec/operations/contacts.d.ts +9 -0
- package/dist/spec/operations/contacts.d.ts.map +1 -0
- package/dist/spec/operations/contacts.js +39 -0
- package/dist/spec/operations/contacts.js.map +1 -0
- package/dist/spec/operations/messages.d.ts +19 -0
- package/dist/spec/operations/messages.d.ts.map +1 -0
- package/dist/spec/operations/messages.js +37 -0
- package/dist/spec/operations/messages.js.map +1 -0
- package/dist/spec/operations/session.d.ts +69 -0
- package/dist/spec/operations/session.d.ts.map +1 -0
- package/dist/spec/operations/session.js +106 -0
- package/dist/spec/operations/session.js.map +1 -0
- package/dist/spec/scalars.d.ts +16 -0
- package/dist/spec/scalars.d.ts.map +1 -0
- package/dist/spec/scalars.js +28 -0
- package/dist/spec/scalars.js.map +1 -0
- package/dist/testing/mock-max.d.ts +29 -0
- package/dist/testing/mock-max.d.ts.map +1 -0
- package/dist/testing/mock-max.js +46 -0
- package/dist/testing/mock-max.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/package.json +58 -0
package/dist/client.js
ADDED
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
import { CliError } from "@leemour/cli-core";
|
|
2
|
+
import { namesFrom, toChat, toContact, toMessage, toProfile } from "./domain/map.js";
|
|
3
|
+
import { wireClient } from "./generated/client.generated.js";
|
|
4
|
+
import { asFirstWord } from "./profile.js";
|
|
5
|
+
import { Connection, ProtocolError } from "./protocol/connection.js";
|
|
6
|
+
import { countsIn, idsOf } from "./runs/events.js";
|
|
7
|
+
import { startSession } from "./session/handshake.js";
|
|
8
|
+
import { buildRequest, checkResponse } from "./spec/index.js";
|
|
9
|
+
/**
|
|
10
|
+
* **The only thing above this line that knows MAX exists.** Commands speak the domain model; the
|
|
11
|
+
* opcodes and the frames stop here, so a different transport underneath changes this file and
|
|
12
|
+
* nothing else (REQUIREMENTS §25).
|
|
13
|
+
*
|
|
14
|
+
* The methods are grouped by subject — `client.chats.list()`, `client.messages.send()` — which is
|
|
15
|
+
* the shape §8 sketched. **There is only this door.** The generated per-operation wrappers sit
|
|
16
|
+
* underneath and stay internal: they return raw MAX payloads, without the resend rule, the name
|
|
17
|
+
* filling or the id conversion that make this safe to point at a real account (`NEED-34`).
|
|
18
|
+
*
|
|
19
|
+
* One instance is one connection. `open` then `close`, always in a `finally`.
|
|
20
|
+
*/
|
|
21
|
+
export class MaxClient {
|
|
22
|
+
#store;
|
|
23
|
+
#connection;
|
|
24
|
+
#warn;
|
|
25
|
+
#cache;
|
|
26
|
+
#offline;
|
|
27
|
+
#events;
|
|
28
|
+
#invoke = ((operation, request) => this.#send(operation, request));
|
|
29
|
+
#wire = wireClient(this.#invoke);
|
|
30
|
+
#login;
|
|
31
|
+
#previousCid = 0;
|
|
32
|
+
#people;
|
|
33
|
+
constructor({ store, timeoutMs, connection, warn, cache, offline = false, events }) {
|
|
34
|
+
this.#store = store;
|
|
35
|
+
this.#connection = connection ?? new Connection(timeoutMs === undefined ? {} : { timeoutMs });
|
|
36
|
+
this.#warn = warn ?? ((message) => process.stderr.write(`${message}\n`));
|
|
37
|
+
this.#cache = cache;
|
|
38
|
+
this.#offline = offline;
|
|
39
|
+
this.#events = events ?? (() => { });
|
|
40
|
+
}
|
|
41
|
+
account = {
|
|
42
|
+
me: () => toProfile(record(this.#session().profile) ?? {}),
|
|
43
|
+
};
|
|
44
|
+
chats = {
|
|
45
|
+
/**
|
|
46
|
+
* Chats come with the login; a limit trims rather than fetching more.
|
|
47
|
+
*
|
|
48
|
+
* **A one-to-one chat has no title of its own** — its name is the other person's, which MAX
|
|
49
|
+
* does not put in the chat object. So the partner is looked up once, for every dialog at a
|
|
50
|
+
* time, and the name is filled in. Without this, `max chats` shows a column of blanks for
|
|
51
|
+
* exactly the chats a person recognises by name.
|
|
52
|
+
*/
|
|
53
|
+
list: async (limit) => {
|
|
54
|
+
if (this.#offline) {
|
|
55
|
+
const cached = this.#recorded(this.#cache?.chats.read(ANY_AGE), "chats");
|
|
56
|
+
return limit === undefined ? cached : cached.slice(0, limit);
|
|
57
|
+
}
|
|
58
|
+
await this.#connectOnce();
|
|
59
|
+
const raw = asArray(this.#session().chats);
|
|
60
|
+
const people = await this.#peopleFor(raw);
|
|
61
|
+
const chats = raw.map((chat) => {
|
|
62
|
+
const mapped = toChat(chat);
|
|
63
|
+
if (mapped.title !== null || mapped.kind !== "dialog")
|
|
64
|
+
return mapped;
|
|
65
|
+
const partner = this.#partnerOf(chat);
|
|
66
|
+
const name = partner === undefined ? null : (people.get(partner)?.name ?? null);
|
|
67
|
+
return { ...mapped, title: name };
|
|
68
|
+
});
|
|
69
|
+
this.#cache?.chats.write(chats);
|
|
70
|
+
return limit === undefined ? chats : chats.slice(0, limit);
|
|
71
|
+
},
|
|
72
|
+
/**
|
|
73
|
+
* Turns what the person typed into a chat id.
|
|
74
|
+
*
|
|
75
|
+
* A number is taken as an id. Anything else is matched against chat titles, exactly first and
|
|
76
|
+
* then as a fragment — and **an ambiguous name is an error, not a guess**: sending to the wrong
|
|
77
|
+
* conversation is not undoable, so the caller is shown the candidates and asked to be specific.
|
|
78
|
+
*/
|
|
79
|
+
resolve: async (reference) => {
|
|
80
|
+
if (/^-?\d+$/.test(reference.trim()))
|
|
81
|
+
return reference.trim();
|
|
82
|
+
const chats = await this.chats.list();
|
|
83
|
+
const wanted = reference.trim().toLowerCase();
|
|
84
|
+
const titled = chats.filter((chat) => chat.title !== null);
|
|
85
|
+
const exact = titled.filter((chat) => chat.title?.toLowerCase() === wanted);
|
|
86
|
+
const matches = exact.length > 0 ? exact : titled.filter((chat) => chat.title?.toLowerCase().includes(wanted));
|
|
87
|
+
if (matches.length === 1 && matches[0])
|
|
88
|
+
return matches[0].id;
|
|
89
|
+
if (matches.length === 0)
|
|
90
|
+
throw new CliError("not_found", `no chat matches "${reference}"`);
|
|
91
|
+
const names = matches.map((chat) => `${chat.title} (${chat.id})`).join(", ");
|
|
92
|
+
throw new CliError("validation_error", `"${reference}" matches ${matches.length} chats: ${names}`);
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
contacts = {
|
|
96
|
+
/** The people this account has a one-to-one chat with, named. */
|
|
97
|
+
list: async () => {
|
|
98
|
+
if (this.#offline)
|
|
99
|
+
return this.#recorded(this.#cache?.contacts.read(ANY_AGE), "contacts");
|
|
100
|
+
await this.#connectOnce();
|
|
101
|
+
const people = await this.#peopleFor(asArray(this.#session().chats));
|
|
102
|
+
const contacts = [...people.values()].filter((contact) => contact.id !== "");
|
|
103
|
+
this.#cache?.contacts.write(contacts);
|
|
104
|
+
return contacts;
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
messages = {
|
|
108
|
+
list: async (chatId, limit = 20) => {
|
|
109
|
+
if (this.#offline)
|
|
110
|
+
return this.#recorded(this.#cache?.messages.read(chatId, limit, ANY_AGE), "messages");
|
|
111
|
+
await this.#connectOnce();
|
|
112
|
+
const session = this.#session();
|
|
113
|
+
// `interactive: false` and no CHAT_MARK: reading history must not mark anything read (§19).
|
|
114
|
+
const answer = await this.#wire.chats.history({
|
|
115
|
+
chatId,
|
|
116
|
+
from: Date.now(),
|
|
117
|
+
forward: 0,
|
|
118
|
+
backward: limit,
|
|
119
|
+
forwardTime: 0,
|
|
120
|
+
backwardTime: 0,
|
|
121
|
+
itemType: "REGULAR",
|
|
122
|
+
getChat: false,
|
|
123
|
+
getMessages: true,
|
|
124
|
+
interactive: false,
|
|
125
|
+
});
|
|
126
|
+
const lookup = { names: namesFrom(session.contacts), ...viewer(this.#store) };
|
|
127
|
+
const messages = asArray(answer.messages).map((raw) => toMessage(raw, chatId, lookup));
|
|
128
|
+
this.#cache?.messages.write(chatId, messages);
|
|
129
|
+
return messages;
|
|
130
|
+
},
|
|
131
|
+
/**
|
|
132
|
+
* Sends one message, retrying **only with the same `cid`**.
|
|
133
|
+
*
|
|
134
|
+
* §17 allows a send to be retried when the protocol has a verified deduplication handle. It has
|
|
135
|
+
* one, measured against MAX on 2026-09-19: sending the same `cid` twice returned the same
|
|
136
|
+
* message id and left **one** copy in the chat — and it held across two separate connections
|
|
137
|
+
* and logins, which is the case a retry actually faces.
|
|
138
|
+
*
|
|
139
|
+
* So one retry, same `cid`, and nothing beyond that. What is still unmeasured is how long the
|
|
140
|
+
* server remembers a `cid`; the two probes were seconds apart. If the retry also fails the
|
|
141
|
+
* answer is `outcome_unknown` — never failed, never sent — and it names the `cid`, because
|
|
142
|
+
* `max send --cid <n>` can then repeat the attempt without risking a second message.
|
|
143
|
+
*/
|
|
144
|
+
send: async (chatId, text, options = {}) => {
|
|
145
|
+
if (this.#offline)
|
|
146
|
+
throw new CliError("validation_error", "`--offline` reads what was recorded; it cannot send");
|
|
147
|
+
await this.#connectOnce();
|
|
148
|
+
const session = this.#session();
|
|
149
|
+
const cid = options.cid ?? this.#nextCid();
|
|
150
|
+
const request = {
|
|
151
|
+
chatId,
|
|
152
|
+
message: { text, cid, elements: [], attaches: [] },
|
|
153
|
+
notify: options.notify ?? true,
|
|
154
|
+
};
|
|
155
|
+
let answer;
|
|
156
|
+
try {
|
|
157
|
+
answer = await this.#wire.messages.send(request);
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
const failure = asCliError(error);
|
|
161
|
+
if (failure.code !== "timeout" && failure.code !== "network_error")
|
|
162
|
+
throw failure;
|
|
163
|
+
// No answer came back, so MAX may already have delivered it. Repeating the identical `cid`
|
|
164
|
+
// is what makes asking again safe rather than reckless.
|
|
165
|
+
try {
|
|
166
|
+
answer = await this.#wire.messages.send(request);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
throw new CliError("outcome_unknown", `the message may or may not have been sent (${failure.message}) — ` +
|
|
170
|
+
`\`max send --cid ${cid}\` repeats the attempt without risking a second copy`, { cid });
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// What the cache holds for this chat is now one message short of the truth.
|
|
174
|
+
this.#cache?.messages.invalidate(chatId);
|
|
175
|
+
const sent = record(answer.message) ?? answer;
|
|
176
|
+
return toMessage(sent, chatId, { names: namesFrom(session.contacts), ...viewer(this.#store) });
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
/**
|
|
180
|
+
* Opens the connection and logs in with the stored token.
|
|
181
|
+
*
|
|
182
|
+
* The login response carries the profile, the chats, the contacts and recent messages, so most
|
|
183
|
+
* commands need no further request — measured against MAX on 2026-09-19.
|
|
184
|
+
*/
|
|
185
|
+
async connect() {
|
|
186
|
+
const token = this.#store.readToken();
|
|
187
|
+
if (!token) {
|
|
188
|
+
// The fix has to carry the profile, or it logs the wrong one in: a name nobody has logged
|
|
189
|
+
// in under is the ordinary shape of this failure now that the first word is the profile.
|
|
190
|
+
throw new CliError("authentication_error", `no session for profile "${this.#store.profile}" — run \`max ${asFirstWord(this.#store.profile)}session start\``);
|
|
191
|
+
}
|
|
192
|
+
const state = this.#store.readState();
|
|
193
|
+
try {
|
|
194
|
+
await this.#connection.open();
|
|
195
|
+
this.#login = await startSession(this.#invoke, { token, deviceId: state.deviceId });
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
throw asCliError(error);
|
|
199
|
+
}
|
|
200
|
+
const viewerId = toProfile(record(this.#login.profile) ?? {}).id;
|
|
201
|
+
this.#store.writeState({
|
|
202
|
+
...state,
|
|
203
|
+
...(viewerId ? { viewerId } : {}),
|
|
204
|
+
logins: state.logins + 1,
|
|
205
|
+
lastLoginAt: new Date().toISOString(),
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
async close() {
|
|
209
|
+
await this.#connection.close();
|
|
210
|
+
}
|
|
211
|
+
/** What `--offline` can answer with, or a refusal that says how to fix it. */
|
|
212
|
+
#recorded(value, what) {
|
|
213
|
+
if (value)
|
|
214
|
+
return value;
|
|
215
|
+
throw new CliError("not_found", `nothing recorded for ${what} on profile "${this.#store.profile}" — run the command once without \`--offline\``);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* **The socket is opened only when something actually needs MAX.**
|
|
219
|
+
*
|
|
220
|
+
* This is the whole point of the cache: a read the cache can answer opens no connection, spends
|
|
221
|
+
* no login, and is over before a socket would have finished its handshake. `connect()` stays
|
|
222
|
+
* public for the one command that must reach MAX to mean anything — starting a session.
|
|
223
|
+
*/
|
|
224
|
+
async #connectOnce() {
|
|
225
|
+
if (!this.#login)
|
|
226
|
+
await this.connect();
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* One request: encode against the specification, send, and compare the answer with what we said
|
|
230
|
+
* it would be.
|
|
231
|
+
*
|
|
232
|
+
* **The comparison never decides anything** (`NEED-35`). A response that gained a field is not a
|
|
233
|
+
* mismatch at all — response shapes are loose. What is left is a field we rely on that stopped
|
|
234
|
+
* being what it was, which is worth one line on stderr and nothing more.
|
|
235
|
+
*/
|
|
236
|
+
async #send(operation, request) {
|
|
237
|
+
const payload = buildRequest(operation, request);
|
|
238
|
+
const started = performance.now();
|
|
239
|
+
const about = { operation: operation.name, opcode: operation.opcode };
|
|
240
|
+
let seq = 0;
|
|
241
|
+
let bytes;
|
|
242
|
+
let answer;
|
|
243
|
+
try {
|
|
244
|
+
answer = await this.#connection.invoke(operation.opcode, payload, (wire) => {
|
|
245
|
+
seq = wire.seq;
|
|
246
|
+
if (wire.phase === "received") {
|
|
247
|
+
bytes = wire.bytes;
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
this.#emit({ event: "request", ...about, seq, bytes: wire.bytes, ...idsOf(request) });
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
catch (error) {
|
|
254
|
+
const failure = asCliError(error);
|
|
255
|
+
// The request that never came back is the one somebody is reading the log for, so it gets a
|
|
256
|
+
// line of its own rather than disappearing with the exception.
|
|
257
|
+
this.#emit({
|
|
258
|
+
event: "response",
|
|
259
|
+
...about,
|
|
260
|
+
seq,
|
|
261
|
+
...(bytes === undefined ? {} : { bytes }),
|
|
262
|
+
durationMs: Math.round(performance.now() - started),
|
|
263
|
+
outcome: "error",
|
|
264
|
+
errorCode: failure.code,
|
|
265
|
+
});
|
|
266
|
+
throw failure;
|
|
267
|
+
}
|
|
268
|
+
const counts = countsIn(answer);
|
|
269
|
+
this.#emit({
|
|
270
|
+
event: "response",
|
|
271
|
+
...about,
|
|
272
|
+
seq,
|
|
273
|
+
...(bytes === undefined ? {} : { bytes }),
|
|
274
|
+
durationMs: Math.round(performance.now() - started),
|
|
275
|
+
...(counts ? { counts } : {}),
|
|
276
|
+
outcome: "ok",
|
|
277
|
+
});
|
|
278
|
+
const note = checkResponse(operation, answer);
|
|
279
|
+
if (note)
|
|
280
|
+
this.#warn(note);
|
|
281
|
+
return answer;
|
|
282
|
+
}
|
|
283
|
+
/** A diagnostic that breaks the command it was describing is worse than no diagnostic. */
|
|
284
|
+
#emit(event) {
|
|
285
|
+
try {
|
|
286
|
+
this.#events(event);
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
// Whoever is keeping the log has a problem; the command does not.
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* A client id that never repeats within a process.
|
|
294
|
+
*
|
|
295
|
+
* `Date.now()` alone is not enough: two sends in the same millisecond get the same number, and if
|
|
296
|
+
* MAX really does deduplicate by `cid` the second message vanishes with no error anywhere. Caught
|
|
297
|
+
* by a test, not by a lost message. Across processes this is still millisecond-grained, which is
|
|
298
|
+
* safe while one invocation sends one message.
|
|
299
|
+
*/
|
|
300
|
+
#nextCid() {
|
|
301
|
+
const now = Date.now();
|
|
302
|
+
this.#previousCid = now > this.#previousCid ? now : this.#previousCid + 1;
|
|
303
|
+
return this.#previousCid;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Names for everyone in these chats, from the login response first and one request for the rest.
|
|
307
|
+
*
|
|
308
|
+
* One `CONTACT_INFO` for all the unknown ids rather than one per chat: a person with forty
|
|
309
|
+
* dialogs should not cost forty round trips, and the login only carries a handful of contacts —
|
|
310
|
+
* six of seventeen dialog partners, measured on a real account.
|
|
311
|
+
*/
|
|
312
|
+
async #peopleFor(chats) {
|
|
313
|
+
if (this.#people)
|
|
314
|
+
return this.#people;
|
|
315
|
+
const people = new Map();
|
|
316
|
+
for (const raw of asArray(this.#session().contacts)) {
|
|
317
|
+
const contact = toContact(raw);
|
|
318
|
+
if (contact.id)
|
|
319
|
+
people.set(contact.id, contact);
|
|
320
|
+
}
|
|
321
|
+
const missing = new Set();
|
|
322
|
+
for (const chat of chats) {
|
|
323
|
+
const partner = this.#partnerOf(chat);
|
|
324
|
+
if (partner !== undefined && !people.has(partner))
|
|
325
|
+
missing.add(partner);
|
|
326
|
+
}
|
|
327
|
+
if (missing.size > 0) {
|
|
328
|
+
const answer = await this.#wire.contacts.info({ contactIds: [...missing] });
|
|
329
|
+
for (const raw of asArray(answer.contacts)) {
|
|
330
|
+
const contact = toContact(raw);
|
|
331
|
+
if (contact.id)
|
|
332
|
+
people.set(contact.id, contact);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
this.#people = people;
|
|
336
|
+
return people;
|
|
337
|
+
}
|
|
338
|
+
/** The other party in a one-to-one chat, if there is exactly one. */
|
|
339
|
+
#partnerOf(chat) {
|
|
340
|
+
const participants = record(chat.participants);
|
|
341
|
+
if (!participants)
|
|
342
|
+
return undefined;
|
|
343
|
+
const viewerId = this.#store.readState().viewerId;
|
|
344
|
+
const others = Object.keys(participants).filter((id) => id !== viewerId);
|
|
345
|
+
return others.length === 1 ? others[0] : undefined;
|
|
346
|
+
}
|
|
347
|
+
#session() {
|
|
348
|
+
if (!this.#login)
|
|
349
|
+
throw new CliError("configuration_error", "connect() was never called");
|
|
350
|
+
return this.#login;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
/** `--offline` was asked for explicitly, so age is not a reason to refuse what was recorded. */
|
|
354
|
+
const ANY_AGE = Number.POSITIVE_INFINITY;
|
|
355
|
+
const viewer = (store) => {
|
|
356
|
+
const viewerId = store.readState().viewerId;
|
|
357
|
+
return viewerId === undefined ? {} : { viewerId };
|
|
358
|
+
};
|
|
359
|
+
const record = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
360
|
+
const asArray = (value) => Array.isArray(value) ? value.filter((item) => record(item) !== undefined) : [];
|
|
361
|
+
/**
|
|
362
|
+
* MAX's own words become our error codes.
|
|
363
|
+
*
|
|
364
|
+
* A refusal naming the token is an authentication problem the user can fix by logging in again;
|
|
365
|
+
* everything else from the far end is `provider_error`, and a connection that died is a network
|
|
366
|
+
* one. Nothing here retries: whether an operation may be repeated is the caller's question.
|
|
367
|
+
*/
|
|
368
|
+
const asCliError = (error) => {
|
|
369
|
+
if (error instanceof CliError)
|
|
370
|
+
return error;
|
|
371
|
+
if (error instanceof ProtocolError) {
|
|
372
|
+
const text = error.message.toLowerCase();
|
|
373
|
+
if (text.includes("token") || text.includes("auth")) {
|
|
374
|
+
return new CliError("authentication_error", `${error.message} — the session may have expired; run \`max session start\``);
|
|
375
|
+
}
|
|
376
|
+
return new CliError("provider_error", error.message, { operation: String(error.opcode) });
|
|
377
|
+
}
|
|
378
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
379
|
+
if (message.includes("did not answer"))
|
|
380
|
+
return new CliError("timeout", message);
|
|
381
|
+
return new CliError("network_error", message);
|
|
382
|
+
};
|
|
383
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../src/commands/account.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGnC,eAAO,MAAM,cAAc,QAAO,OAuBjC,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { forCommand } from "./context.js";
|
|
3
|
+
export const accountCommand = () => {
|
|
4
|
+
const command = new Command("account").description("the account this profile is logged in as");
|
|
5
|
+
command
|
|
6
|
+
.command("show")
|
|
7
|
+
.description("who this profile is logged in as")
|
|
8
|
+
.action(async function () {
|
|
9
|
+
const { renderer, createClient, run } = forCommand(this.optsWithGlobals());
|
|
10
|
+
await run("account show", async (events) => {
|
|
11
|
+
const client = createClient({ events });
|
|
12
|
+
try {
|
|
13
|
+
await client.connect();
|
|
14
|
+
renderer.result(client.account.me());
|
|
15
|
+
}
|
|
16
|
+
finally {
|
|
17
|
+
// Nothing below this line: an open socket keeps the process alive after the answer printed.
|
|
18
|
+
await client.close();
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
return command;
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=account.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.js","sourceRoot":"","sources":["../../src/commands/account.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEzC,MAAM,CAAC,MAAM,cAAc,GAAG,GAAY,EAAE;IAC1C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC,WAAW,CAAC,0CAA0C,CAAC,CAAA;IAE9F,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,kCAAkC,CAAC;SAC/C,MAAM,CAAC,KAAK;QACX,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAA;QAE1E,MAAM,GAAG,CAAC,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YACzC,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;YAEvC,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,OAAO,EAAE,CAAA;gBACtB,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAA;YACtC,CAAC;oBAAS,CAAC;gBACT,4FAA4F;gBAC5F,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;YACtB,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEJ,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
/**
|
|
3
|
+
* The way out, and it matters more than it looks.
|
|
4
|
+
*
|
|
5
|
+
* Everything else in this tool can be re-run; a cache is the one part that remembers being wrong.
|
|
6
|
+
* While the schema is still moving, the fix for a cache that misbehaves has to be a command rather
|
|
7
|
+
* than finding a file and deleting it.
|
|
8
|
+
*/
|
|
9
|
+
export declare const cacheCommand: () => Command;
|
|
10
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/commands/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAInC;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,QAAO,OA2B/B,CAAA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { openProfileCache } from "../cache/index.js";
|
|
3
|
+
import { resolveOutput } from "../output.js";
|
|
4
|
+
/**
|
|
5
|
+
* The way out, and it matters more than it looks.
|
|
6
|
+
*
|
|
7
|
+
* Everything else in this tool can be re-run; a cache is the one part that remembers being wrong.
|
|
8
|
+
* While the schema is still moving, the fix for a cache that misbehaves has to be a command rather
|
|
9
|
+
* than finding a file and deleting it.
|
|
10
|
+
*/
|
|
11
|
+
export const cacheCommand = () => {
|
|
12
|
+
const command = new Command("cache").description("the local copy of chats, contacts and messages");
|
|
13
|
+
command
|
|
14
|
+
.command("clear")
|
|
15
|
+
.description("forget everything this profile has cached")
|
|
16
|
+
.action(async function () {
|
|
17
|
+
const options = this.optsWithGlobals();
|
|
18
|
+
const { renderer } = resolveOutput(options);
|
|
19
|
+
const cache = await openProfileCache(options.profile, { onProblem: (message) => renderer.note(message) });
|
|
20
|
+
if (!cache) {
|
|
21
|
+
renderer.result({ profile: options.profile, cleared: false });
|
|
22
|
+
renderer.note("there is no cache for this profile");
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
cache.clear();
|
|
27
|
+
renderer.result({ profile: options.profile, cleared: true });
|
|
28
|
+
renderer.success(`forgot everything cached for "${options.profile}"`);
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
cache.close();
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
return command;
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/commands/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAE5C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,GAAY,EAAE;IACxC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,gDAAgD,CAAC,CAAA;IAElG,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,2CAA2C,CAAC;SACxD,MAAM,CAAC,KAAK;QACX,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,CAAA;QACtC,MAAM,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;QAC3C,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAEzG,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;YAC7D,QAAQ,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAA;YACnD,OAAM;QACR,CAAC;QAED,IAAI,CAAC;YACH,KAAK,CAAC,KAAK,EAAE,CAAA;YACb,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;YAC5D,QAAQ,CAAC,OAAO,CAAC,iCAAiC,OAAO,CAAC,OAAO,GAAG,CAAC,CAAA;QACvE,CAAC;gBAAS,CAAC;YACT,KAAK,CAAC,KAAK,EAAE,CAAA;QACf,CAAC;IACH,CAAC,CAAC,CAAA;IAEJ,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chats.d.ts","sourceRoot":"","sources":["../../src/commands/chats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAInC,eAAO,MAAM,YAAY,QAAO,OA0B/B,CAAA"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { openProfileCache } from "../cache/index.js";
|
|
3
|
+
import { forCommand } from "./context.js";
|
|
4
|
+
export const chatsCommand = () => {
|
|
5
|
+
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());
|
|
14
|
+
const cache = await openProfileCache(settings.profile, { onProblem: (message) => renderer.note(message) });
|
|
15
|
+
await run("chats list", async (events) => {
|
|
16
|
+
const client = createClient({ events, ...(cache ? { cache } : {}) });
|
|
17
|
+
try {
|
|
18
|
+
renderer.result(await client.chats.list(settings.limit));
|
|
19
|
+
}
|
|
20
|
+
finally {
|
|
21
|
+
await client.close();
|
|
22
|
+
cache?.close();
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
return command;
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=chats.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
/**
|
|
3
|
+
* The people this account has a one-to-one chat with.
|
|
4
|
+
*
|
|
5
|
+
* Not "the address book": MAX has an opcode that tsmax calls `CONTACT_LIST` and the protocol
|
|
6
|
+
* documentation calls `GET_BLOCKED`, and until somebody has watched what it actually returns, this
|
|
7
|
+
* lists what we can establish without guessing.
|
|
8
|
+
*/
|
|
9
|
+
export declare const contactsCommand: () => Command;
|
|
10
|
+
//# sourceMappingURL=contacts.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { openProfileCache } from "../cache/index.js";
|
|
3
|
+
import { forCommand } from "./context.js";
|
|
4
|
+
/**
|
|
5
|
+
* The people this account has a one-to-one chat with.
|
|
6
|
+
*
|
|
7
|
+
* Not "the address book": MAX has an opcode that tsmax calls `CONTACT_LIST` and the protocol
|
|
8
|
+
* documentation calls `GET_BLOCKED`, and until somebody has watched what it actually returns, this
|
|
9
|
+
* lists what we can establish without guessing.
|
|
10
|
+
*/
|
|
11
|
+
export const contactsCommand = () => {
|
|
12
|
+
const command = new Command("contacts").description("people you have a one-to-one chat with");
|
|
13
|
+
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))
|
|
17
|
+
.action(async function () {
|
|
18
|
+
const { renderer, settings, createClient, run } = forCommand(this.optsWithGlobals());
|
|
19
|
+
const cache = await openProfileCache(settings.profile, { onProblem: (message) => renderer.note(message) });
|
|
20
|
+
await run("contacts list", async (events) => {
|
|
21
|
+
const client = createClient({ events, ...(cache ? { cache } : {}) });
|
|
22
|
+
try {
|
|
23
|
+
renderer.result((await client.contacts.list()).slice(0, settings.limit));
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
await client.close();
|
|
27
|
+
cache?.close();
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
return command;
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=contacts.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Renderer, RenderFormat } from "@leemour/cli-core";
|
|
2
|
+
import { MaxClient, type MaxClientOptions } from "../client.js";
|
|
3
|
+
import { type GlobalFlags, type Settings } from "../config.js";
|
|
4
|
+
import { SessionStore } from "../session/store.js";
|
|
5
|
+
export interface CommandContext {
|
|
6
|
+
settings: Settings;
|
|
7
|
+
renderer: Renderer;
|
|
8
|
+
format: RenderFormat;
|
|
9
|
+
store: SessionStore;
|
|
10
|
+
/** Not connected yet: the action owns the `finally` that closes it — and the cache, if it opened one. */
|
|
11
|
+
createClient: (extra?: Partial<Omit<MaxClientOptions, "store">>) => MaxClient;
|
|
12
|
+
/**
|
|
13
|
+
* Runs the body with diagnostics on and the run finalized on every path, if anything asked for
|
|
14
|
+
* either. The body gets the emitter to hand to `createClient`.
|
|
15
|
+
*/
|
|
16
|
+
run: <T>(command: string, body: (events: MaxClientOptions["events"]) => Promise<T>) => Promise<T>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Everything a command needs, resolved once — and **the only place a `MaxClient` is built.**
|
|
20
|
+
*
|
|
21
|
+
* One construction site is what keeps the protocol note quiet under `--quiet`: a command building
|
|
22
|
+
* its own client gets the default `warn`, which writes straight to stderr past the renderer
|
|
23
|
+
* (`BUG-7`). With eight commands, "remember to pass `warn`" is a rule that gets broken once and
|
|
24
|
+
* then nobody can see it.
|
|
25
|
+
*
|
|
26
|
+
* It is also where `--record` stops being a flag and becomes a setting: `recorded` takes what
|
|
27
|
+
* `resolveSettings` decided — flag, then environment, then the configuration file — rather than
|
|
28
|
+
* what `commander` happened to parse.
|
|
29
|
+
*
|
|
30
|
+
* The cache is not opened here on purpose — only the reading commands want one, and opening it
|
|
31
|
+
* would create a database file for `session end`, which will never read it.
|
|
32
|
+
*/
|
|
33
|
+
export declare const forCommand: (flags: GlobalFlags) => CommandContext;
|
|
34
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAC/D,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC/D,OAAO,EAAE,KAAK,WAAW,EAAmB,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAA;AAG/E,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAElD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,QAAQ,CAAA;IAClB,QAAQ,EAAE,QAAQ,CAAA;IAClB,MAAM,EAAE,YAAY,CAAA;IACpB,KAAK,EAAE,YAAY,CAAA;IACnB,yGAAyG;IACzG,YAAY,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC,KAAK,SAAS,CAAA;IAC7E;;;OAGG;IACH,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;CAClG;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,WAAW,KAAG,cAwB/C,CAAA"}
|