@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
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { MaxClient } from "../client.js";
|
|
2
|
+
import { resolveSettings } from "../config.js";
|
|
3
|
+
import { resolveOutput } from "../output.js";
|
|
4
|
+
import { recorded } from "../runs/recording.js";
|
|
5
|
+
import { SessionStore } from "../session/store.js";
|
|
6
|
+
/**
|
|
7
|
+
* Everything a command needs, resolved once — and **the only place a `MaxClient` is built.**
|
|
8
|
+
*
|
|
9
|
+
* One construction site is what keeps the protocol note quiet under `--quiet`: a command building
|
|
10
|
+
* its own client gets the default `warn`, which writes straight to stderr past the renderer
|
|
11
|
+
* (`BUG-7`). With eight commands, "remember to pass `warn`" is a rule that gets broken once and
|
|
12
|
+
* then nobody can see it.
|
|
13
|
+
*
|
|
14
|
+
* It is also where `--record` stops being a flag and becomes a setting: `recorded` takes what
|
|
15
|
+
* `resolveSettings` decided — flag, then environment, then the configuration file — rather than
|
|
16
|
+
* what `commander` happened to parse.
|
|
17
|
+
*
|
|
18
|
+
* The cache is not opened here on purpose — only the reading commands want one, and opening it
|
|
19
|
+
* would create a database file for `session end`, which will never read it.
|
|
20
|
+
*/
|
|
21
|
+
export const forCommand = (flags) => {
|
|
22
|
+
const settings = resolveSettings(flags);
|
|
23
|
+
const { renderer, format } = resolveOutput(settings);
|
|
24
|
+
const store = new SessionStore({ profile: settings.profile });
|
|
25
|
+
return {
|
|
26
|
+
settings,
|
|
27
|
+
renderer,
|
|
28
|
+
format,
|
|
29
|
+
store,
|
|
30
|
+
createClient: (extra = {}) => new MaxClient({ store, timeoutMs: settings.timeoutMs, warn: renderer.note, ...extra }),
|
|
31
|
+
run: (command, body) => recorded({
|
|
32
|
+
command,
|
|
33
|
+
profile: settings.profile,
|
|
34
|
+
options: { record: settings.record, verbose: settings.verbose },
|
|
35
|
+
format,
|
|
36
|
+
keepDays: settings.keepRunsForDays,
|
|
37
|
+
}, body),
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAyB,MAAM,cAAc,CAAA;AAC/D,OAAO,EAAoB,eAAe,EAAiB,MAAM,cAAc,CAAA;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAgBlD;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAkB,EAAkB,EAAE;IAC/D,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA;IACvC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAA;IACpD,MAAM,KAAK,GAAG,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAA;IAE7D,OAAO;QACL,QAAQ;QACR,QAAQ;QACR,MAAM;QACN,KAAK;QACL,YAAY,EAAE,CAAC,KAAK,GAAG,EAAE,EAAE,EAAE,CAC3B,IAAI,SAAS,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC;QACxF,GAAG,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CACrB,QAAQ,CACN;YACE,OAAO;YACP,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE;YAC/D,MAAM;YACN,QAAQ,EAAE,QAAQ,CAAC,eAAe;SACnC,EACD,IAAI,CACL;KACJ,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { openProfileCache } from "../cache/index.js";
|
|
3
|
+
import { forCommand } from "./context.js";
|
|
4
|
+
export const messagesCommand = () => {
|
|
5
|
+
const command = new Command("messages").description("read and send messages in a chat");
|
|
6
|
+
/**
|
|
7
|
+
* Observational, and deliberately so: this reads `CHAT_HISTORY` and never sends `CHAT_MARK`, so
|
|
8
|
+
* looking at a conversation does not tell anyone you read it (REQUIREMENTS §19).
|
|
9
|
+
*/
|
|
10
|
+
command
|
|
11
|
+
.command("list")
|
|
12
|
+
.argument("<chat>", "chat id, or part of a chat name")
|
|
13
|
+
.description("recent messages in a chat, oldest first")
|
|
14
|
+
.option("--limit <n>", "how many to read", (value) => Number.parseInt(value, 10))
|
|
15
|
+
.action(async function (chat) {
|
|
16
|
+
const { renderer, settings, createClient, run } = forCommand(this.optsWithGlobals());
|
|
17
|
+
const cache = await openProfileCache(settings.profile, { onProblem: (message) => renderer.note(message) });
|
|
18
|
+
await run("messages list", async (events) => {
|
|
19
|
+
const client = createClient({ events, ...(cache ? { cache } : {}) });
|
|
20
|
+
try {
|
|
21
|
+
const chatId = await client.chats.resolve(chat);
|
|
22
|
+
renderer.result(await client.messages.list(chatId, settings.limit));
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
await client.close();
|
|
26
|
+
cache?.close();
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
/**
|
|
31
|
+
* One message, one command, no retry.
|
|
32
|
+
*
|
|
33
|
+
* There is no `--dry-run` here: the target and the text are both in the line the person typed, so
|
|
34
|
+
* a preview would restate the command back at them (REQUIREMENTS §21). What this command does owe
|
|
35
|
+
* the caller is honesty about an outcome it does not know — see `MaxClient.messages.send`.
|
|
36
|
+
*/
|
|
37
|
+
command
|
|
38
|
+
.command("send")
|
|
39
|
+
.argument("<chat>", "chat id, or part of a chat name")
|
|
40
|
+
.argument("<text>", "what to say")
|
|
41
|
+
.description("send one text message")
|
|
42
|
+
.option("--cid <n>", "reuse a client id from an earlier ambiguous send; MAX collapses the duplicate", (value) => Number.parseInt(value, 10))
|
|
43
|
+
.action(async function (chat, text) {
|
|
44
|
+
const options = this.optsWithGlobals();
|
|
45
|
+
const { renderer, settings, createClient, run } = forCommand(options);
|
|
46
|
+
const cache = await openProfileCache(settings.profile, { onProblem: (message) => renderer.note(message) });
|
|
47
|
+
await run("messages send", async (events) => {
|
|
48
|
+
const client = createClient({ events, ...(cache ? { cache } : {}) });
|
|
49
|
+
try {
|
|
50
|
+
const chatId = await client.chats.resolve(chat);
|
|
51
|
+
const sent = await client.messages.send(chatId, text, options.cid === undefined ? {} : { cid: options.cid });
|
|
52
|
+
renderer.result(sent);
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
await client.close();
|
|
56
|
+
cache?.close();
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
return command;
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/commands/messages.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
/**
|
|
3
|
+
* What this tool did, when it was asked to keep the record.
|
|
4
|
+
*
|
|
5
|
+
* Reading the log is not itself an action worth recording, so **nothing here starts a run** — a
|
|
6
|
+
* `max runs list` that created a run directory while listing them would be its own joke.
|
|
7
|
+
*/
|
|
8
|
+
export declare const runsCommand: () => Command;
|
|
9
|
+
//# sourceMappingURL=runs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runs.d.ts","sourceRoot":"","sources":["../../src/commands/runs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAInC;;;;;GAKG;AACH,eAAO,MAAM,WAAW,QAAO,OAgD9B,CAAA"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { CliError } from "@leemour/cli-core";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { resolveOutput } from "../output.js";
|
|
4
|
+
import { findRun, listRuns, readEvents, runsDirFor } from "../runs/run.js";
|
|
5
|
+
/**
|
|
6
|
+
* What this tool did, when it was asked to keep the record.
|
|
7
|
+
*
|
|
8
|
+
* Reading the log is not itself an action worth recording, so **nothing here starts a run** — a
|
|
9
|
+
* `max runs list` that created a run directory while listing them would be its own joke.
|
|
10
|
+
*/
|
|
11
|
+
export const runsCommand = () => {
|
|
12
|
+
const command = new Command("runs").description("recorded runs — what this tool did, and when");
|
|
13
|
+
command
|
|
14
|
+
.command("list")
|
|
15
|
+
.description("recorded runs, newest first")
|
|
16
|
+
.option("--limit <n>", "how many to show", (value) => Number.parseInt(value, 10), 20)
|
|
17
|
+
.action(function () {
|
|
18
|
+
const options = this.optsWithGlobals();
|
|
19
|
+
const { renderer } = resolveOutput(options);
|
|
20
|
+
const runs = listRuns(runsDirFor());
|
|
21
|
+
renderer.result(runs.slice(0, options.limit));
|
|
22
|
+
// An empty list reads as broken otherwise, and the reason is that nothing asked for a
|
|
23
|
+
// record — recording is off unless it is asked for (`NEED-52`). The explanation is a
|
|
24
|
+
// diagnostic, so stdout still carries one JSON value and nothing else.
|
|
25
|
+
if (runs.length === 0)
|
|
26
|
+
renderer.note("nothing recorded — a run is kept only with `--record`");
|
|
27
|
+
});
|
|
28
|
+
command
|
|
29
|
+
.command("show")
|
|
30
|
+
.argument("<run-id>", "an id from `max runs list`")
|
|
31
|
+
.description("one run: what it was, and one line per request")
|
|
32
|
+
.action(function (id) {
|
|
33
|
+
const options = this.optsWithGlobals();
|
|
34
|
+
const { renderer } = resolveOutput(options);
|
|
35
|
+
const found = runOrRefuse(id);
|
|
36
|
+
// Both, because neither answers the question on its own: the metadata says how it ended and
|
|
37
|
+
// the events say where it went.
|
|
38
|
+
renderer.result({ ...found.metadata, directory: found.dir, events: readEvents(found.dir).map(readable) });
|
|
39
|
+
});
|
|
40
|
+
command
|
|
41
|
+
.command("path")
|
|
42
|
+
.argument("<run-id>", "an id from `max runs list`")
|
|
43
|
+
.description("the directory holding one run")
|
|
44
|
+
.action(function (id) {
|
|
45
|
+
const options = this.optsWithGlobals();
|
|
46
|
+
const { renderer } = resolveOutput(options);
|
|
47
|
+
// One JSON value on stdout here too, with no exception for convenience (`NEED-88`): a script
|
|
48
|
+
// reads `--json | jq -r .path`, and a terminal prints the bare path as a labelled line.
|
|
49
|
+
renderer.result({ path: runOrRefuse(id).dir });
|
|
50
|
+
});
|
|
51
|
+
return command;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Drops what Pino puts on every line: the level, and the run id, command and profile that are the
|
|
55
|
+
* same for the whole run and are printed above it anyway.
|
|
56
|
+
*
|
|
57
|
+
* Without this the table is five constant columns wide before it reaches the opcode, and the
|
|
58
|
+
* durations and sizes — the reason anyone opened it — fall off the right of an 80-column terminal.
|
|
59
|
+
* `max runs path <id>` still gives the file, envelope and all.
|
|
60
|
+
*/
|
|
61
|
+
const readable = ({ level, runId, command, profile, ...event }) => event;
|
|
62
|
+
const runOrRefuse = (id) => {
|
|
63
|
+
const found = findRun(runsDirFor(), id);
|
|
64
|
+
if (!found)
|
|
65
|
+
throw new CliError("not_found", `no recorded run "${id}" — \`max runs list\` shows what there is`);
|
|
66
|
+
return found;
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=runs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runs.js","sourceRoot":"","sources":["../../src/commands/runs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { commandWords, refuseCommandName, rootOf } from "../profile.js";
|
|
3
|
+
import { readSecret } from "../session/prompt.js";
|
|
4
|
+
import { forCommand } from "./context.js";
|
|
5
|
+
export const sessionCommand = () => {
|
|
6
|
+
const command = new Command("session").description("the stored MAX session for this profile");
|
|
7
|
+
/**
|
|
8
|
+
* For now, importing a token obtained elsewhere — from `web.max.ru`, or from another client.
|
|
9
|
+
*
|
|
10
|
+
* This is not a stopgap: it is the escape hatch that keeps every other command usable when our
|
|
11
|
+
* own login flow meets a captcha or an unusual second factor, and it is how the slice is tested
|
|
12
|
+
* without an SMS per run. The interactive phone-and-code flow lands beside it, not instead of it.
|
|
13
|
+
*
|
|
14
|
+
* **The token is asked for, not passed.** A token in argv is read by `ps` and kept by shell
|
|
15
|
+
* history, and a file leaves a copy nobody deletes, so with `MAX_TOKEN` unset it is read from the
|
|
16
|
+
* 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
|
+
*/
|
|
19
|
+
command
|
|
20
|
+
.command("start")
|
|
21
|
+
.description("store a MAX session for this profile")
|
|
22
|
+
.action(async function () {
|
|
23
|
+
const { renderer, settings, store, createClient, run } = forCommand(this.optsWithGlobals());
|
|
24
|
+
// Creation is the only moment the collision can still be explained; after this the name is
|
|
25
|
+
// written down and `max <name>` would silently be a command instead.
|
|
26
|
+
refuseCommandName(settings.profile, commandWords(rootOf(this)));
|
|
27
|
+
const token = process.env.MAX_TOKEN?.trim() || (await readSecret("MAX token: "));
|
|
28
|
+
// Before the run directory: nothing was attempted, so there is nothing to record.
|
|
29
|
+
if (!token) {
|
|
30
|
+
renderer.failure("no token given");
|
|
31
|
+
process.exitCode = 2;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
store.writeToken(token);
|
|
35
|
+
await run("session start", async (events) => {
|
|
36
|
+
const client = createClient({ events });
|
|
37
|
+
try {
|
|
38
|
+
await client.connect();
|
|
39
|
+
const profile = client.account.me();
|
|
40
|
+
renderer.result({ profile, stored: true });
|
|
41
|
+
renderer.success(`logged in as ${profile.name ?? profile.id}`);
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
await client.close();
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
/**
|
|
49
|
+
* Local only, for now: it forgets the token and the device identity on this machine.
|
|
50
|
+
*
|
|
51
|
+
* It does **not** send LOGOUT (opcode 20), which would end the session on MAX's side too — and
|
|
52
|
+
* with it the browser tab the token came from. That distinction is in the output rather than
|
|
53
|
+
* glossed over: a forgotten token that is still live elsewhere is a different thing from a
|
|
54
|
+
* revoked one.
|
|
55
|
+
*/
|
|
56
|
+
command
|
|
57
|
+
.command("end")
|
|
58
|
+
.description("forget the stored session for this profile")
|
|
59
|
+
.action(async function () {
|
|
60
|
+
const { renderer, store, run } = forCommand(this.optsWithGlobals());
|
|
61
|
+
// It contacts nobody, so the run holds no events — but forgetting a session is an action, and
|
|
62
|
+
// "when did this profile stop working" is a question the record is kept to answer.
|
|
63
|
+
await run("session end", async () => {
|
|
64
|
+
const had = store.forget();
|
|
65
|
+
renderer.result({ profile: store.profile, forgotten: had, revokedOnServer: false });
|
|
66
|
+
if (had)
|
|
67
|
+
renderer.success(`forgot the session for "${store.profile}" on this machine`);
|
|
68
|
+
else
|
|
69
|
+
renderer.note(`there was no session for "${store.profile}"`);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
return command;
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/commands/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACjD,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,yCAAyC,CAAC,CAAA;IAE7F;;;;;;;;;;;OAWG;IACH,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,sCAAsC,CAAC;SACnD,MAAM,CAAC,KAAK;QACX,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAA;QAE3F,2FAA2F;QAC3F,qEAAqE;QACrE,iBAAiB,CAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAE/D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,UAAU,CAAC,aAAa,CAAC,CAAC,CAAA;QAEhF,kFAAkF;QAClF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,QAAQ,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAA;YAClC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;YACpB,OAAM;QACR,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;QAEvB,MAAM,GAAG,CAAC,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAC1C,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;YAEvC,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,OAAO,EAAE,CAAA;gBACtB,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,CAAA;gBACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;gBAC1C,QAAQ,CAAC,OAAO,CAAC,gBAAgB,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC,CAAA;YAChE,CAAC;oBAAS,CAAC;gBACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;YACtB,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEJ;;;;;;;OAOG;IACH,OAAO;SACJ,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,4CAA4C,CAAC;SACzD,MAAM,CAAC,KAAK;QACX,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAA;QAEnE,8FAA8F;QAC9F,mFAAmF;QACnF,MAAM,GAAG,CAAC,aAAa,EAAE,KAAK,IAAI,EAAE;YAClC,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,EAAE,CAAA;YAE1B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAA;YACnF,IAAI,GAAG;gBAAE,QAAQ,CAAC,OAAO,CAAC,2BAA2B,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;;gBACjF,QAAQ,CAAC,IAAI,CAAC,6BAA6B,KAAK,CAAC,OAAO,GAAG,CAAC,CAAA;QACnE,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEJ,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
export declare const configSchema: v.StrictObjectSchema<{
|
|
3
|
+
readonly defaultProfile: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
4
|
+
readonly profiles: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.StrictObjectSchema<{
|
|
5
|
+
readonly limit: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, undefined>;
|
|
6
|
+
readonly timeoutMs: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, undefined>;
|
|
7
|
+
readonly color: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
8
|
+
/** The run log reads these two; nothing records anything until it exists. */
|
|
9
|
+
readonly record: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
10
|
+
readonly keepRunsForDays: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, undefined>;
|
|
11
|
+
}, undefined>, undefined>, {}>;
|
|
12
|
+
}, undefined>;
|
|
13
|
+
export type Config = v.InferOutput<typeof configSchema>;
|
|
14
|
+
/** Whatever the command line carried. Everything is optional: absent means "not given here". */
|
|
15
|
+
export interface GlobalFlags {
|
|
16
|
+
profile?: string;
|
|
17
|
+
json?: boolean;
|
|
18
|
+
quiet?: boolean;
|
|
19
|
+
verbose?: boolean;
|
|
20
|
+
limit?: number;
|
|
21
|
+
record?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface Settings {
|
|
24
|
+
profile: string;
|
|
25
|
+
json: boolean;
|
|
26
|
+
quiet: boolean;
|
|
27
|
+
verbose: boolean;
|
|
28
|
+
/** Unset means "decide from the terminal", which is `resolveOutput`'s job, not this one's. */
|
|
29
|
+
color: boolean | undefined;
|
|
30
|
+
limit: number;
|
|
31
|
+
/** Unset means the transport's own default; the number lives in `protocol/connection.ts`. */
|
|
32
|
+
timeoutMs: number | undefined;
|
|
33
|
+
record: boolean;
|
|
34
|
+
keepRunsForDays: number;
|
|
35
|
+
/** Named in errors and in `max --help`, so a person can find the file that decided this. */
|
|
36
|
+
configPath: string;
|
|
37
|
+
}
|
|
38
|
+
export interface ResolveOptions {
|
|
39
|
+
env?: NodeJS.ProcessEnv;
|
|
40
|
+
/** Tests pass a temporary directory; nothing else should need this. */
|
|
41
|
+
configDir?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* **Flag, then environment, then the configuration file, then the built-in default.** One place,
|
|
45
|
+
* so no command can decide the order differently from another.
|
|
46
|
+
*
|
|
47
|
+
* Two things already jump this queue and are documented rather than re-litigated here:
|
|
48
|
+
* `MAX_TOKEN` outranks the keyring (`cli-core`'s `Credentials.read`), and `MAX_CONFIG_DIR`,
|
|
49
|
+
* `MAX_STATE_DIR` or `MAX_CACHE_DIR` move the whole installation — including which keyring entry
|
|
50
|
+
* a profile means (`ARCHITECTURE.md` §13).
|
|
51
|
+
*/
|
|
52
|
+
export declare const resolveSettings: (flags?: GlobalFlags, { env, configDir }?: ResolveOptions) => Settings;
|
|
53
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +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"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { CliError, configFilePath, loadConfigFile, resolvePaths } from "@leemour/cli-core";
|
|
2
|
+
import * as v from "valibot";
|
|
3
|
+
import { DEFAULT_PROFILE, usableProfileName } from "./profile.js";
|
|
4
|
+
const APP = "max-cli";
|
|
5
|
+
const DEFAULT_LIMIT = 20;
|
|
6
|
+
const DEFAULT_KEEP_RUNS_FOR_DAYS = 30;
|
|
7
|
+
const count = v.pipe(v.number(), v.integer(), v.minValue(1));
|
|
8
|
+
/**
|
|
9
|
+
* ⚠ `strictObject`, not `object`: an unknown key is an error here.
|
|
10
|
+
*
|
|
11
|
+
* `object()` drops what it does not recognise — measured with valibot 1.5, `{ limitt: 5 }` parses
|
|
12
|
+
* to `{}` and reports nothing — so a misspelled setting would run with the default and never say
|
|
13
|
+
* why. That is the failure this schema exists to prevent, and it is the **opposite** of the rule
|
|
14
|
+
* for MAX's own answers, which keep unknown fields on purpose (`NEED-35`).
|
|
15
|
+
*
|
|
16
|
+
* **No field here can hold a secret.** No token, no phone number, no chat id: a schema with
|
|
17
|
+
* nowhere to put one is stronger than a rule saying do not put one there.
|
|
18
|
+
*/
|
|
19
|
+
const profileSettings = v.strictObject({
|
|
20
|
+
limit: v.optional(count),
|
|
21
|
+
timeoutMs: v.optional(count),
|
|
22
|
+
color: v.optional(v.boolean()),
|
|
23
|
+
/** The run log reads these two; nothing records anything until it exists. */
|
|
24
|
+
record: v.optional(v.boolean()),
|
|
25
|
+
keepRunsForDays: v.optional(count),
|
|
26
|
+
});
|
|
27
|
+
export const configSchema = v.strictObject({
|
|
28
|
+
defaultProfile: v.optional(v.string()),
|
|
29
|
+
profiles: v.optional(v.record(v.string(), profileSettings), {}),
|
|
30
|
+
});
|
|
31
|
+
/**
|
|
32
|
+
* **Flag, then environment, then the configuration file, then the built-in default.** One place,
|
|
33
|
+
* so no command can decide the order differently from another.
|
|
34
|
+
*
|
|
35
|
+
* Two things already jump this queue and are documented rather than re-litigated here:
|
|
36
|
+
* `MAX_TOKEN` outranks the keyring (`cli-core`'s `Credentials.read`), and `MAX_CONFIG_DIR`,
|
|
37
|
+
* `MAX_STATE_DIR` or `MAX_CACHE_DIR` move the whole installation — including which keyring entry
|
|
38
|
+
* a profile means (`ARCHITECTURE.md` §13).
|
|
39
|
+
*/
|
|
40
|
+
export const resolveSettings = (flags = {}, { env = process.env, configDir } = {}) => {
|
|
41
|
+
const paths = resolvePaths({ appName: APP, prefix: "MAX", env });
|
|
42
|
+
const configPath = configFilePath(configDir ?? paths.config);
|
|
43
|
+
const config = readConfig(configPath);
|
|
44
|
+
const profile = usableProfileName(flags.profile ?? given(env.MAX_PROFILE) ?? config.defaultProfile ?? DEFAULT_PROFILE);
|
|
45
|
+
const configured = config.profiles[profile] ?? {};
|
|
46
|
+
const settings = {
|
|
47
|
+
profile,
|
|
48
|
+
json: flags.json === true,
|
|
49
|
+
quiet: flags.quiet === true,
|
|
50
|
+
verbose: flags.verbose === true,
|
|
51
|
+
color: configured.color,
|
|
52
|
+
limit: flags.limit ?? configured.limit ?? DEFAULT_LIMIT,
|
|
53
|
+
timeoutMs: configured.timeoutMs,
|
|
54
|
+
record: flags.record ?? configured.record ?? false,
|
|
55
|
+
keepRunsForDays: configured.keepRunsForDays ?? DEFAULT_KEEP_RUNS_FOR_DAYS,
|
|
56
|
+
configPath,
|
|
57
|
+
};
|
|
58
|
+
// The file was checked by the schema; a flag was not, and `--limit abc` is `NaN` by the time it
|
|
59
|
+
// gets here, which slices an array to nothing without complaining.
|
|
60
|
+
if (!Number.isInteger(settings.limit) || settings.limit < 1) {
|
|
61
|
+
throw new CliError("validation_error", `--limit takes a whole number from 1 upwards, not ${flags.limit}`);
|
|
62
|
+
}
|
|
63
|
+
return settings;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* A missing file is not an error — it is a program nobody has configured. A malformed one is, in
|
|
67
|
+
* every output mode: an agent reading JSON deserves the same refusal a person gets, and silently
|
|
68
|
+
* falling back to the defaults is what makes a typo cost an afternoon.
|
|
69
|
+
*/
|
|
70
|
+
const readConfig = (path) => {
|
|
71
|
+
try {
|
|
72
|
+
return loadConfigFile(path, configSchema, () => ({ profiles: {} }));
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
throw new CliError("configuration_error", error instanceof Error ? error.message : String(error));
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
/** An environment variable set to the empty string is not a value; it is the shell being unset. */
|
|
79
|
+
const given = (value) => {
|
|
80
|
+
const trimmed = value?.trim();
|
|
81
|
+
return trimmed === undefined || trimmed === "" ? undefined : trimmed;
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type Payload } from "../protocol/frame.js";
|
|
2
|
+
import type { Chat, Contact, Id, Message, Profile } from "./models.js";
|
|
3
|
+
/**
|
|
4
|
+
* Wire shapes into our own types.
|
|
5
|
+
*
|
|
6
|
+
* **Tolerant when reading** (REQUIREMENTS §29): an unknown field is ignored, a missing one becomes
|
|
7
|
+
* `null`, and nothing here throws. This is an unofficial protocol — a response that gained a field
|
|
8
|
+
* must not break a command, and a response that lost one must say so rather than invent a value.
|
|
9
|
+
*/
|
|
10
|
+
export interface NameLookup {
|
|
11
|
+
/** Display names by user id, built from the `contacts` the login response carries. */
|
|
12
|
+
names?: Map<Id, string>;
|
|
13
|
+
/** Whose account this is, so a message can say whether it is ours. */
|
|
14
|
+
viewerId?: Id;
|
|
15
|
+
}
|
|
16
|
+
export declare const toChat: (raw: Payload) => Chat;
|
|
17
|
+
export declare const toMessage: (raw: Payload, chatId: Id, lookup?: NameLookup) => Message;
|
|
18
|
+
export declare const toContact: (raw: Payload) => Contact;
|
|
19
|
+
export declare const toProfile: (raw: Payload) => Profile;
|
|
20
|
+
/** The names a login response carries, so a message can name its sender without another request. */
|
|
21
|
+
export declare const namesFrom: (contacts: unknown) => Map<Id, string>;
|
|
22
|
+
//# sourceMappingURL=map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../../src/domain/map.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,KAAK,EAAc,IAAI,EAAY,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAE5F;;;;;;GAMG;AAEH,MAAM,WAAW,UAAU;IACzB,sFAAsF;IACtF,KAAK,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;IACvB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,EAAE,CAAA;CACd;AAED,eAAO,MAAM,MAAM,GAAI,KAAK,OAAO,KAAG,IAOpC,CAAA;AAEF,eAAO,MAAM,SAAS,GAAI,KAAK,OAAO,EAAE,QAAQ,EAAE,EAAE,SAAQ,UAAe,KAAG,OAc7E,CAAA;AAED,eAAO,MAAM,SAAS,GAAI,KAAK,OAAO,KAAG,OAKvC,CAAA;AAEF,eAAO,MAAM,SAAS,GAAI,KAAK,OAAO,KAAG,OAQxC,CAAA;AAED,oGAAoG;AACpG,eAAO,MAAM,SAAS,GAAI,UAAU,OAAO,KAAG,GAAG,CAAC,EAAE,EAAE,MAAM,CAY3D,CAAA"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { asId } from "../protocol/frame.js";
|
|
2
|
+
export const toChat = (raw) => ({
|
|
3
|
+
id: asId(raw.id) ?? "",
|
|
4
|
+
title: text(raw.title),
|
|
5
|
+
kind: chatKind(raw.type),
|
|
6
|
+
unreadCount: count(raw.newMessages),
|
|
7
|
+
lastMessageAt: timestamp(raw.lastEventTime ?? asRecord(raw.lastMessage)?.time),
|
|
8
|
+
participantsCount: count(raw.participantsCount),
|
|
9
|
+
});
|
|
10
|
+
export const toMessage = (raw, chatId, lookup = {}) => {
|
|
11
|
+
const senderId = asId(raw.sender);
|
|
12
|
+
return {
|
|
13
|
+
id: asId(raw.id) ?? "",
|
|
14
|
+
chatId,
|
|
15
|
+
senderId: senderId ?? null,
|
|
16
|
+
senderName: senderId ? (lookup.names?.get(senderId) ?? null) : null,
|
|
17
|
+
timestamp: timestamp(raw.time) ?? new Date(0).toISOString(),
|
|
18
|
+
editedAt: timestamp(raw.updateTime),
|
|
19
|
+
text: text(raw.text) ?? "",
|
|
20
|
+
outgoing: lookup.viewerId === undefined || senderId === undefined ? null : senderId === lookup.viewerId,
|
|
21
|
+
attachments: attachments(raw.attaches),
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export const toContact = (raw) => ({
|
|
25
|
+
id: asId(raw.id) ?? "",
|
|
26
|
+
name: displayName(raw.names) ?? text(raw.name),
|
|
27
|
+
username: text(raw.link),
|
|
28
|
+
description: text(raw.description),
|
|
29
|
+
});
|
|
30
|
+
export const toProfile = (raw) => {
|
|
31
|
+
const contact = asRecord(raw.contact) ?? raw;
|
|
32
|
+
return {
|
|
33
|
+
id: asId(contact.id) ?? "",
|
|
34
|
+
name: displayName(contact.names) ?? text(contact.name),
|
|
35
|
+
phone: phone(contact.phones) ?? text(contact.phone),
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
/** The names a login response carries, so a message can name its sender without another request. */
|
|
39
|
+
export const namesFrom = (contacts) => {
|
|
40
|
+
const names = new Map();
|
|
41
|
+
if (!Array.isArray(contacts))
|
|
42
|
+
return names;
|
|
43
|
+
for (const entry of contacts) {
|
|
44
|
+
const contact = asRecord(entry);
|
|
45
|
+
if (!contact)
|
|
46
|
+
continue;
|
|
47
|
+
const id = asId(contact.id);
|
|
48
|
+
const name = displayName(contact.names) ?? text(contact.name);
|
|
49
|
+
if (id && name)
|
|
50
|
+
names.set(id, name);
|
|
51
|
+
}
|
|
52
|
+
return names;
|
|
53
|
+
};
|
|
54
|
+
const asRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
55
|
+
const text = (value) => (typeof value === "string" && value !== "" ? value : null);
|
|
56
|
+
const count = (value) => {
|
|
57
|
+
const asNumber = typeof value === "bigint" ? Number(value) : value;
|
|
58
|
+
return typeof asNumber === "number" && Number.isFinite(asNumber) ? asNumber : null;
|
|
59
|
+
};
|
|
60
|
+
/** MAX sends Unix milliseconds; output is ISO 8601, which sorts, parses and needs no timezone guess. */
|
|
61
|
+
const timestamp = (value) => {
|
|
62
|
+
const ms = count(value);
|
|
63
|
+
if (ms === null || ms <= 0)
|
|
64
|
+
return null;
|
|
65
|
+
const date = new Date(ms);
|
|
66
|
+
return Number.isNaN(date.getTime()) ? null : date.toISOString();
|
|
67
|
+
};
|
|
68
|
+
const chatKind = (value) => {
|
|
69
|
+
switch (typeof value === "string" ? value.toUpperCase() : "") {
|
|
70
|
+
case "DIALOG":
|
|
71
|
+
return "dialog";
|
|
72
|
+
case "CHAT":
|
|
73
|
+
return "group";
|
|
74
|
+
case "CHANNEL":
|
|
75
|
+
return "channel";
|
|
76
|
+
default:
|
|
77
|
+
return "unknown";
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
/** `names` is a list of `{name, type}`; the full name wins, and any name beats none. */
|
|
81
|
+
const displayName = (value) => {
|
|
82
|
+
if (!Array.isArray(value))
|
|
83
|
+
return null;
|
|
84
|
+
const entries = value.map(asRecord).filter((entry) => entry !== undefined);
|
|
85
|
+
const full = entries.find((entry) => entry.type === "FULL_NAME");
|
|
86
|
+
return text(full?.name) ?? text(entries[0]?.name);
|
|
87
|
+
};
|
|
88
|
+
const phone = (value) => {
|
|
89
|
+
if (!Array.isArray(value))
|
|
90
|
+
return null;
|
|
91
|
+
const first = asRecord(value[0]);
|
|
92
|
+
const number = first?.number;
|
|
93
|
+
return text(number) ?? (typeof number === "number" || typeof number === "bigint" ? `+${number}` : null);
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Attachment **metadata**, never its content. A message that carries a photo says so; downloading
|
|
97
|
+
* it is a different command that does not exist yet (§11 of the brief).
|
|
98
|
+
*/
|
|
99
|
+
const attachments = (value) => {
|
|
100
|
+
if (!Array.isArray(value))
|
|
101
|
+
return [];
|
|
102
|
+
return value
|
|
103
|
+
.map(asRecord)
|
|
104
|
+
.filter((entry) => entry !== undefined)
|
|
105
|
+
.map((entry) => ({ kind: typeof entry._type === "string" ? entry._type.toLowerCase() : "unknown" }));
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map.js","sourceRoot":"","sources":["../../src/domain/map.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAgB,MAAM,sBAAsB,CAAA;AAkBzD,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,GAAY,EAAQ,EAAE,CAAC,CAAC;IAC7C,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE;IACtB,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;IACtB,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;IACxB,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC;IACnC,aAAa,EAAE,SAAS,CAAC,GAAG,CAAC,aAAa,IAAI,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC;IAC9E,iBAAiB,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC;CAChD,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAY,EAAE,MAAU,EAAE,SAAqB,EAAE,EAAW,EAAE;IACtF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAEjC,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE;QACtB,MAAM;QACN,QAAQ,EAAE,QAAQ,IAAI,IAAI;QAC1B,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;QACnE,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;QAC3D,QAAQ,EAAE,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC;QACnC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE;QAC1B,QAAQ,EAAE,MAAM,CAAC,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ;QACvG,WAAW,EAAE,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC;KACvC,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAY,EAAW,EAAE,CAAC,CAAC;IACnD,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE;IACtB,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;IAC9C,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;IACxB,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC;CACnC,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAY,EAAW,EAAE;IACjD,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,CAAA;IAE5C,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE;QAC1B,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;QACtD,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;KACpD,CAAA;AACH,CAAC,CAAA;AAED,oGAAoG;AACpG,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,QAAiB,EAAmB,EAAE;IAC9D,MAAM,KAAK,GAAG,IAAI,GAAG,EAAc,CAAA;IACnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAA;IAE1C,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;QAC/B,IAAI,CAAC,OAAO;YAAE,SAAQ;QACtB,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAC3B,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC7D,IAAI,EAAE,IAAI,IAAI;YAAE,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;IACrC,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAuB,EAAE,CACvD,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,KAAiB,CAAC,CAAC,CAAC,SAAS,CAAA;AAEvG,MAAM,IAAI,GAAG,CAAC,KAAc,EAAiB,EAAE,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;AAE1G,MAAM,KAAK,GAAG,CAAC,KAAc,EAAiB,EAAE;IAC9C,MAAM,QAAQ,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;IAClE,OAAO,OAAO,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAA;AACpF,CAAC,CAAA;AAED,wGAAwG;AACxG,MAAM,SAAS,GAAG,CAAC,KAAc,EAAiB,EAAE;IAClD,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAA;IACvB,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IACvC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAA;IACzB,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAA;AACjE,CAAC,CAAA;AAED,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAY,EAAE;IAC5C,QAAQ,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAC7D,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAA;QACjB,KAAK,MAAM;YACT,OAAO,OAAO,CAAA;QAChB,KAAK,SAAS;YACZ,OAAO,SAAS,CAAA;QAClB;YACE,OAAO,SAAS,CAAA;IACpB,CAAC;AACH,CAAC,CAAA;AAED,wFAAwF;AACxF,MAAM,WAAW,GAAG,CAAC,KAAc,EAAiB,EAAE;IACpD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACtC,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAoB,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAA;IAC5F,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAA;IAChE,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;AACnD,CAAC,CAAA;AAED,MAAM,KAAK,GAAG,CAAC,KAAc,EAAiB,EAAE;IAC9C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACtC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IAChC,MAAM,MAAM,GAAG,KAAK,EAAE,MAAM,CAAA;IAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;AACzG,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,WAAW,GAAG,CAAC,KAAc,EAAgB,EAAE;IACnD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IACpC,OAAO,KAAK;SACT,GAAG,CAAC,QAAQ,CAAC;SACb,MAAM,CAAC,CAAC,KAAK,EAAoB,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC;SACxD,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;AACxG,CAAC,CAAA"}
|