@leemour/max-cli 0.5.0 → 0.7.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 (261) hide show
  1. package/README.md +22 -5
  2. package/dist/cache/index.d.ts +1 -0
  3. package/dist/cache/index.d.ts.map +1 -1
  4. package/dist/cache/index.js +4 -4
  5. package/dist/cache/index.js.map +1 -1
  6. package/dist/cache/store.d.ts.map +1 -1
  7. package/dist/cache/store.js +1 -0
  8. package/dist/cache/store.js.map +1 -1
  9. package/dist/client.d.ts +230 -7
  10. package/dist/client.d.ts.map +1 -1
  11. package/dist/client.js +959 -78
  12. package/dist/client.js.map +1 -1
  13. package/dist/commands/account.d.ts.map +1 -1
  14. package/dist/commands/account.js +71 -3
  15. package/dist/commands/account.js.map +1 -1
  16. package/dist/commands/chats.d.ts.map +1 -1
  17. package/dist/commands/chats.js +159 -0
  18. package/dist/commands/chats.js.map +1 -1
  19. package/dist/commands/commands.d.ts +8 -0
  20. package/dist/commands/commands.d.ts.map +1 -0
  21. package/dist/commands/commands.js +36 -0
  22. package/dist/commands/commands.js.map +1 -0
  23. package/dist/commands/complete.d.ts +10 -0
  24. package/dist/commands/complete.d.ts.map +1 -0
  25. package/dist/commands/complete.js +89 -0
  26. package/dist/commands/complete.js.map +1 -0
  27. package/dist/commands/config.d.ts.map +1 -1
  28. package/dist/commands/config.js +6 -2
  29. package/dist/commands/config.js.map +1 -1
  30. package/dist/commands/contacts.d.ts +3 -0
  31. package/dist/commands/contacts.d.ts.map +1 -1
  32. package/dist/commands/contacts.js +85 -0
  33. package/dist/commands/contacts.js.map +1 -1
  34. package/dist/commands/context.d.ts +26 -1
  35. package/dist/commands/context.d.ts.map +1 -1
  36. package/dist/commands/context.js +47 -6
  37. package/dist/commands/context.js.map +1 -1
  38. package/dist/commands/folders.d.ts +4 -0
  39. package/dist/commands/folders.d.ts.map +1 -0
  40. package/dist/commands/folders.js +76 -0
  41. package/dist/commands/folders.js.map +1 -0
  42. package/dist/commands/inbox.d.ts +14 -0
  43. package/dist/commands/inbox.d.ts.map +1 -0
  44. package/dist/commands/inbox.js +90 -0
  45. package/dist/commands/inbox.js.map +1 -0
  46. package/dist/commands/mcp.d.ts +3 -0
  47. package/dist/commands/mcp.d.ts.map +1 -0
  48. package/dist/commands/mcp.js +17 -0
  49. package/dist/commands/mcp.js.map +1 -0
  50. package/dist/commands/messages.d.ts.map +1 -1
  51. package/dist/commands/messages.js +90 -4
  52. package/dist/commands/messages.js.map +1 -1
  53. package/dist/commands/reactions.d.ts +3 -0
  54. package/dist/commands/reactions.d.ts.map +1 -0
  55. package/dist/commands/reactions.js +43 -0
  56. package/dist/commands/reactions.js.map +1 -0
  57. package/dist/commands/recipients.d.ts +9 -0
  58. package/dist/commands/recipients.d.ts.map +1 -0
  59. package/dist/commands/recipients.js +68 -0
  60. package/dist/commands/recipients.js.map +1 -0
  61. package/dist/commands/sends.d.ts +4 -0
  62. package/dist/commands/sends.d.ts.map +1 -0
  63. package/dist/commands/sends.js +21 -0
  64. package/dist/commands/sends.js.map +1 -0
  65. package/dist/commands/serve.d.ts +10 -0
  66. package/dist/commands/serve.d.ts.map +1 -0
  67. package/dist/commands/serve.js +50 -0
  68. package/dist/commands/serve.js.map +1 -0
  69. package/dist/commands/session.d.ts.map +1 -1
  70. package/dist/commands/session.js +84 -16
  71. package/dist/commands/session.js.map +1 -1
  72. package/dist/commands/skill.d.ts.map +1 -1
  73. package/dist/commands/skill.js +2 -1
  74. package/dist/commands/skill.js.map +1 -1
  75. package/dist/commands/update.d.ts +7 -0
  76. package/dist/commands/update.d.ts.map +1 -0
  77. package/dist/commands/update.js +53 -0
  78. package/dist/commands/update.js.map +1 -0
  79. package/dist/commands/watch.d.ts +9 -0
  80. package/dist/commands/watch.d.ts.map +1 -0
  81. package/dist/commands/watch.js +68 -0
  82. package/dist/commands/watch.js.map +1 -0
  83. package/dist/config.d.ts +24 -1
  84. package/dist/config.d.ts.map +1 -1
  85. package/dist/config.js +43 -4
  86. package/dist/config.js.map +1 -1
  87. package/dist/domain/map.d.ts +10 -1
  88. package/dist/domain/map.d.ts.map +1 -1
  89. package/dist/domain/map.js +51 -1
  90. package/dist/domain/map.js.map +1 -1
  91. package/dist/domain/models.d.ts +80 -0
  92. package/dist/domain/models.d.ts.map +1 -1
  93. package/dist/domain/models.js.map +1 -1
  94. package/dist/generated/client.generated.d.ts +36 -0
  95. package/dist/generated/client.generated.d.ts.map +1 -1
  96. package/dist/generated/client.generated.js +36 -0
  97. package/dist/generated/client.generated.js.map +1 -1
  98. package/dist/generated/opcodes.generated.d.ts +37 -5
  99. package/dist/generated/opcodes.generated.d.ts.map +1 -1
  100. package/dist/generated/opcodes.generated.js +37 -5
  101. package/dist/generated/opcodes.generated.js.map +1 -1
  102. package/dist/generated/operations.generated.d.ts +245 -3
  103. package/dist/generated/operations.generated.d.ts.map +1 -1
  104. package/dist/generated/operations.generated.js +36 -4
  105. package/dist/generated/operations.generated.js.map +1 -1
  106. package/dist/markdown.d.ts +18 -0
  107. package/dist/markdown.d.ts.map +1 -0
  108. package/dist/markdown.js +52 -0
  109. package/dist/markdown.js.map +1 -0
  110. package/dist/mcp/confirm.d.ts +24 -0
  111. package/dist/mcp/confirm.d.ts.map +1 -0
  112. package/dist/mcp/confirm.js +53 -0
  113. package/dist/mcp/confirm.js.map +1 -0
  114. package/dist/mcp/instructions.d.ts +10 -0
  115. package/dist/mcp/instructions.d.ts.map +1 -0
  116. package/dist/mcp/instructions.js +25 -0
  117. package/dist/mcp/instructions.js.map +1 -0
  118. package/dist/mcp/server.d.ts +23 -0
  119. package/dist/mcp/server.d.ts.map +1 -0
  120. package/dist/mcp/server.js +38 -0
  121. package/dist/mcp/server.js.map +1 -0
  122. package/dist/mcp/session.d.ts +28 -0
  123. package/dist/mcp/session.d.ts.map +1 -0
  124. package/dist/mcp/session.js +91 -0
  125. package/dist/mcp/session.js.map +1 -0
  126. package/dist/mcp/tools.d.ts +8 -0
  127. package/dist/mcp/tools.d.ts.map +1 -0
  128. package/dist/mcp/tools.js +274 -0
  129. package/dist/mcp/tools.js.map +1 -0
  130. package/dist/program.d.ts.map +1 -1
  131. package/dist/program.js +27 -0
  132. package/dist/program.js.map +1 -1
  133. package/dist/protocol/connection.d.ts +10 -8
  134. package/dist/protocol/connection.d.ts.map +1 -1
  135. package/dist/protocol/connection.js +64 -7
  136. package/dist/protocol/connection.js.map +1 -1
  137. package/dist/protocol/frame.d.ts +2 -1
  138. package/dist/protocol/frame.d.ts.map +1 -1
  139. package/dist/protocol/frame.js.map +1 -1
  140. package/dist/rendering/messages.d.ts.map +1 -1
  141. package/dist/rendering/messages.js +21 -7
  142. package/dist/rendering/messages.js.map +1 -1
  143. package/dist/resolve.d.ts +15 -0
  144. package/dist/resolve.d.ts.map +1 -0
  145. package/dist/resolve.js +48 -0
  146. package/dist/resolve.js.map +1 -0
  147. package/dist/sends/guard.d.ts +27 -0
  148. package/dist/sends/guard.d.ts.map +1 -0
  149. package/dist/sends/guard.js +52 -0
  150. package/dist/sends/guard.js.map +1 -0
  151. package/dist/sends/journal.d.ts +42 -0
  152. package/dist/sends/journal.d.ts.map +1 -0
  153. package/dist/sends/journal.js +40 -0
  154. package/dist/sends/journal.js.map +1 -0
  155. package/dist/sends/recipients.d.ts +29 -0
  156. package/dist/sends/recipients.d.ts.map +1 -0
  157. package/dist/sends/recipients.js +62 -0
  158. package/dist/sends/recipients.js.map +1 -0
  159. package/dist/server/lines.d.ts +9 -0
  160. package/dist/server/lines.d.ts.map +1 -0
  161. package/dist/server/lines.js +25 -0
  162. package/dist/server/lines.js.map +1 -0
  163. package/dist/server/server-connection.d.ts +35 -0
  164. package/dist/server/server-connection.d.ts.map +1 -0
  165. package/dist/server/server-connection.js +195 -0
  166. package/dist/server/server-connection.js.map +1 -0
  167. package/dist/server/server.d.ts +62 -0
  168. package/dist/server/server.d.ts.map +1 -0
  169. package/dist/server/server.js +297 -0
  170. package/dist/server/server.js.map +1 -0
  171. package/dist/server/start.d.ts +12 -0
  172. package/dist/server/start.d.ts.map +1 -0
  173. package/dist/server/start.js +41 -0
  174. package/dist/server/start.js.map +1 -0
  175. package/dist/server/subscribe.d.ts +9 -0
  176. package/dist/server/subscribe.d.ts.map +1 -0
  177. package/dist/server/subscribe.js +26 -0
  178. package/dist/server/subscribe.js.map +1 -0
  179. package/dist/session/adopt.d.ts.map +1 -1
  180. package/dist/session/adopt.js +7 -6
  181. package/dist/session/adopt.js.map +1 -1
  182. package/dist/session/browser.d.ts +55 -0
  183. package/dist/session/browser.d.ts.map +1 -0
  184. package/dist/session/browser.js +319 -0
  185. package/dist/session/browser.js.map +1 -0
  186. package/dist/session/handshake.d.ts +2 -0
  187. package/dist/session/handshake.d.ts.map +1 -1
  188. package/dist/session/handshake.js +3 -1
  189. package/dist/session/handshake.js.map +1 -1
  190. package/dist/session/login.d.ts +20 -0
  191. package/dist/session/login.d.ts.map +1 -0
  192. package/dist/session/login.js +66 -0
  193. package/dist/session/login.js.map +1 -0
  194. package/dist/session/prompt.d.ts +3 -1
  195. package/dist/session/prompt.d.ts.map +1 -1
  196. package/dist/session/prompt.js +2 -2
  197. package/dist/session/prompt.js.map +1 -1
  198. package/dist/session/qr-terminal.d.ts +9 -0
  199. package/dist/session/qr-terminal.d.ts.map +1 -0
  200. package/dist/session/qr-terminal.js +34 -0
  201. package/dist/session/qr-terminal.js.map +1 -0
  202. package/dist/session/store.d.ts +4 -0
  203. package/dist/session/store.d.ts.map +1 -1
  204. package/dist/session/store.js +6 -0
  205. package/dist/session/store.js.map +1 -1
  206. package/dist/spec/define.d.ts.map +1 -1
  207. package/dist/spec/define.js +14 -1
  208. package/dist/spec/define.js.map +1 -1
  209. package/dist/spec/index.d.ts.map +1 -1
  210. package/dist/spec/index.js +38 -5
  211. package/dist/spec/index.js.map +1 -1
  212. package/dist/spec/operations/account.d.ts +20 -0
  213. package/dist/spec/operations/account.d.ts.map +1 -0
  214. package/dist/spec/operations/account.js +62 -0
  215. package/dist/spec/operations/account.js.map +1 -0
  216. package/dist/spec/operations/chats.d.ts +54 -0
  217. package/dist/spec/operations/chats.d.ts.map +1 -1
  218. package/dist/spec/operations/chats.js +121 -0
  219. package/dist/spec/operations/chats.js.map +1 -1
  220. package/dist/spec/operations/contacts.d.ts +19 -1
  221. package/dist/spec/operations/contacts.d.ts.map +1 -1
  222. package/dist/spec/operations/contacts.js +49 -6
  223. package/dist/spec/operations/contacts.js.map +1 -1
  224. package/dist/spec/operations/folders.d.ts +24 -0
  225. package/dist/spec/operations/folders.d.ts.map +1 -0
  226. package/dist/spec/operations/folders.js +64 -0
  227. package/dist/spec/operations/folders.js.map +1 -0
  228. package/dist/spec/operations/login.d.ts +64 -0
  229. package/dist/spec/operations/login.d.ts.map +1 -0
  230. package/dist/spec/operations/login.js +99 -0
  231. package/dist/spec/operations/login.js.map +1 -0
  232. package/dist/spec/operations/messages.d.ts +67 -3
  233. package/dist/spec/operations/messages.d.ts.map +1 -1
  234. package/dist/spec/operations/messages.js +126 -13
  235. package/dist/spec/operations/messages.js.map +1 -1
  236. package/dist/spec/operations/session.d.ts +7 -0
  237. package/dist/spec/operations/session.d.ts.map +1 -1
  238. package/dist/spec/operations/session.js +17 -0
  239. package/dist/spec/operations/session.js.map +1 -1
  240. package/dist/spec/operations/uploads.d.ts +18 -0
  241. package/dist/spec/operations/uploads.d.ts.map +1 -0
  242. package/dist/spec/operations/uploads.js +35 -0
  243. package/dist/spec/operations/uploads.js.map +1 -0
  244. package/dist/testing/mock-max.d.ts +15 -4
  245. package/dist/testing/mock-max.d.ts.map +1 -1
  246. package/dist/testing/mock-max.js +16 -3
  247. package/dist/testing/mock-max.js.map +1 -1
  248. package/dist/testing/sandbox.js +3 -0
  249. package/dist/testing/sandbox.js.map +1 -1
  250. package/dist/update.d.ts +36 -0
  251. package/dist/update.d.ts.map +1 -0
  252. package/dist/update.js +70 -0
  253. package/dist/update.js.map +1 -0
  254. package/dist/upload.d.ts +10 -0
  255. package/dist/upload.d.ts.map +1 -0
  256. package/dist/upload.js +61 -0
  257. package/dist/upload.js.map +1 -0
  258. package/dist/version.d.ts +1 -1
  259. package/dist/version.js +1 -1
  260. package/package.json +16 -3
  261. package/skills/max-cli/SKILL.md +23 -3
@@ -0,0 +1,297 @@
1
+ import { chmodSync, mkdirSync, rmSync } from "node:fs";
2
+ import { connect, createServer } from "node:net";
3
+ import { dirname } from "node:path";
4
+ import { CliError } from "@leemour/cli-core";
5
+ import { MaxClient } from "../client.js";
6
+ import { Connection, ProtocolError } from "../protocol/connection.js";
7
+ import { fromLine, lineReader, toLine } from "./lines.js";
8
+ import { READS } from "./server-connection.js";
9
+ /** The web client's keep-alive interval (web.max.ru bundle, 2026-09-24). A different one is a fingerprint. */
10
+ const PING_EVERY_MS = 30_000;
11
+ /** A login MAX counts; after one, the next background login waits at least this long. */
12
+ const REFRESH_EVERY_MS = 60_000;
13
+ /**
14
+ * **One logged-in connection per profile, kept open** (`MAX-16`), and a Unix socket beside the
15
+ * profile's state for local readers.
16
+ *
17
+ * It reopens REQUIREMENTS §3 and §18 on purpose and only here: every other command stays one-shot.
18
+ * What it does on the wire copies web.max.ru — a ping every 30 s, MAX's pings answered, each new
19
+ * message acknowledged (`Connection` with `live`). It never marks anything read and never sends.
20
+ *
21
+ * The socket answers `{"subscribe": true}` with a stream of `ServerEvent` lines and
22
+ * `{"status": true}` with one. For a command reusing the connection (`ServerConnection`) it answers
23
+ * `{"id", "login": true}` with the login it holds, and `{"id", "opcode", "payload"}` by passing the
24
+ * request to MAX — **reads only** (`NEED-185`). Anything that writes goes on the command's own
25
+ * connection, through the send guards, which live in the client and nowhere else.
26
+ */
27
+ export class MaxServer {
28
+ #options;
29
+ #subscribers = new Set();
30
+ #listener;
31
+ #client;
32
+ #ping;
33
+ #retry;
34
+ #attempt = 0;
35
+ #stopped = false;
36
+ /** A push touched the chats in a way the login snapshot cannot follow; it is not handed out. */
37
+ #stale = false;
38
+ #refresh;
39
+ #lastRefresh = 0;
40
+ #lastUse = Date.now();
41
+ #idle;
42
+ #finish;
43
+ /** Settles when the server stops — cleanly, or with the error that stopped it. */
44
+ done;
45
+ constructor(options) {
46
+ this.#options = options;
47
+ this.done = new Promise((resolve, reject) => {
48
+ this.#finish = (error) => (error ? reject(error) : resolve());
49
+ });
50
+ }
51
+ get connected() {
52
+ return this.#client !== undefined;
53
+ }
54
+ /** Logs in first: a token that does not work should fail here, before anything listens. */
55
+ async start() {
56
+ try {
57
+ await this.#connect();
58
+ await this.#listen();
59
+ }
60
+ finally {
61
+ rmSync(startingPath(this.#options.store), { force: true });
62
+ }
63
+ const { idleMs } = this.#options;
64
+ if (idleMs !== undefined) {
65
+ this.#idle = setInterval(() => {
66
+ if (this.#subscribers.size === 0 && Date.now() - this.#lastUse >= idleMs) {
67
+ this.#options.note(`nobody has used it for ${Math.round(idleMs / 60_000)} min — stopping`);
68
+ void this.stop();
69
+ }
70
+ }, Math.min(idleMs, 30_000));
71
+ }
72
+ }
73
+ async stop(error) {
74
+ if (this.#stopped)
75
+ return;
76
+ this.#stopped = true;
77
+ clearInterval(this.#ping);
78
+ clearTimeout(this.#retry);
79
+ clearTimeout(this.#refresh);
80
+ clearInterval(this.#idle);
81
+ for (const socket of this.#subscribers)
82
+ socket.destroy();
83
+ this.#subscribers.clear();
84
+ await new Promise((resolve) => (this.#listener ? this.#listener.close(() => resolve()) : resolve()));
85
+ rmSync(this.#options.store.socketPath(), { force: true });
86
+ await this.#client?.close();
87
+ this.#client = undefined;
88
+ this.#finish?.(error);
89
+ }
90
+ /**
91
+ * Logs in on a new connection and, once that worked, makes it the server's — closing the one it
92
+ * replaces, if any. Pushes that arrive before the login finishes are held and replayed, not
93
+ * dropped: `Connection` has already acknowledged them, so MAX will not send them again.
94
+ */
95
+ async #connect() {
96
+ const { store, cache, timeoutMs, events } = this.#options;
97
+ let mine;
98
+ const early = [];
99
+ const connection = (this.#options.connection ??
100
+ ((hooks) => new Connection({ ...hooks, live: true, ...(timeoutMs ? { timeoutMs } : {}) })))({
101
+ onEvent: (frame) => {
102
+ if (mine)
103
+ this.#pushed(mine, frame.opcode, frame.payload ?? {});
104
+ else
105
+ early.push([frame.opcode, frame.payload ?? {}]);
106
+ },
107
+ onClose: (error) => {
108
+ if (mine && mine === this.#client)
109
+ this.#lost(error);
110
+ },
111
+ });
112
+ const client = new MaxClient({
113
+ store,
114
+ connection,
115
+ fullLogin: true,
116
+ warn: this.#options.note,
117
+ ...(cache ? { cache } : {}),
118
+ ...(events ? { events } : {}),
119
+ });
120
+ try {
121
+ await client.connect();
122
+ }
123
+ catch (error) {
124
+ // A socket left open after a refused login keeps the process alive after it said it failed.
125
+ await client.close();
126
+ throw error;
127
+ }
128
+ const replaced = this.#client;
129
+ mine = client;
130
+ this.#client = client;
131
+ this.#attempt = 0;
132
+ this.#stale = false;
133
+ this.#lastRefresh = Date.now();
134
+ clearInterval(this.#ping);
135
+ this.#ping = setInterval(() => {
136
+ client.live.ping().catch(() => { });
137
+ }, this.#options.pingEveryMs ?? PING_EVERY_MS);
138
+ if (replaced)
139
+ await replaced.close().catch(() => { });
140
+ else
141
+ this.#broadcast({ event: "status", connected: true, at: new Date().toISOString() });
142
+ for (const [opcode, payload] of early)
143
+ this.#pushed(client, opcode, payload);
144
+ }
145
+ #pushed(client, opcode, payload) {
146
+ if (!client.live.patch(opcode, payload))
147
+ this.#goneStale();
148
+ client.live
149
+ .message(opcode, payload)
150
+ .then((message) => message && this.#broadcast({ event: "message", message }))
151
+ .catch((error) => this.#options.note(`a pushed message could not be read: ${error.message}`));
152
+ }
153
+ /**
154
+ * The login can no longer be handed out. Rather than wait for a drop that may be hours away, log
155
+ * in again in the background — at most once a minute, since each is a login MAX counts.
156
+ */
157
+ #goneStale() {
158
+ this.#stale = true;
159
+ if (this.#refresh || this.#stopped)
160
+ return;
161
+ const every = this.#options.refreshEveryMs ?? REFRESH_EVERY_MS;
162
+ const wait = Math.max(0, this.#lastRefresh + every - Date.now());
163
+ this.#refresh = setTimeout(() => {
164
+ this.#connect()
165
+ .catch((error) => this.#options.note(`could not log in again: ${error.message}`))
166
+ .finally(() => {
167
+ this.#refresh = undefined;
168
+ });
169
+ }, wait);
170
+ }
171
+ #lost(error) {
172
+ clearInterval(this.#ping);
173
+ const client = this.#client;
174
+ this.#client = undefined;
175
+ client?.close().catch(() => { });
176
+ if (this.#stopped)
177
+ return;
178
+ this.#broadcast({ event: "status", connected: false, at: new Date().toISOString() });
179
+ this.#reconnectLater(error);
180
+ }
181
+ #reconnectLater(error) {
182
+ const wait = (this.#options.retryAfterMs ?? backoff)(this.#attempt);
183
+ this.#attempt += 1;
184
+ this.#options.note(`${error.message} — connecting again in ${Math.round(wait / 1000)}s`);
185
+ this.#retry = setTimeout(() => {
186
+ this.#connect().catch((failure) => {
187
+ // A token MAX no longer takes will not start working on the next attempt.
188
+ if (failure instanceof CliError && failure.code === "authentication_error")
189
+ this.stop(failure);
190
+ else
191
+ this.#reconnectLater(failure);
192
+ });
193
+ }, wait);
194
+ }
195
+ #broadcast(event) {
196
+ const line = toLine(event);
197
+ for (const socket of this.#subscribers)
198
+ socket.write(line);
199
+ }
200
+ async #listen() {
201
+ const path = this.#options.store.socketPath();
202
+ if (await answers(path)) {
203
+ throw new CliError("validation_error", `a server is already running for profile "${this.#options.store.profile}"`);
204
+ }
205
+ // Nobody answers on it, so it is what a crashed server left behind.
206
+ rmSync(path, { force: true });
207
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
208
+ const listener = createServer((socket) => this.#serve(socket));
209
+ await new Promise((resolve, reject) => {
210
+ listener.once("error", reject);
211
+ listener.listen(path, () => resolve());
212
+ });
213
+ chmodSync(path, 0o600);
214
+ this.#listener = listener;
215
+ }
216
+ #serve(socket) {
217
+ socket.on("error", () => this.#subscribers.delete(socket));
218
+ socket.on("close", () => {
219
+ this.#subscribers.delete(socket);
220
+ this.#lastUse = Date.now();
221
+ });
222
+ socket.on("data", lineReader((line) => {
223
+ this.#request(socket, line).catch(() => socket.destroy());
224
+ }));
225
+ }
226
+ async #request(socket, line) {
227
+ let request;
228
+ try {
229
+ request = fromLine(line);
230
+ }
231
+ catch {
232
+ socket.write(toLine({ error: { code: "bad_request", message: "one JSON object per line" } }));
233
+ return;
234
+ }
235
+ const status = { event: "status", connected: this.connected, at: new Date().toISOString() };
236
+ const { id } = request;
237
+ this.#lastUse = Date.now();
238
+ if (request.subscribe === true) {
239
+ this.#subscribers.add(socket);
240
+ socket.write(toLine(status));
241
+ }
242
+ else if (request.status === true) {
243
+ socket.write(toLine(status));
244
+ }
245
+ else if (request.stop === true) {
246
+ // Only the owner can reach this socket (mode 600); `max session end` asks, so a forgotten
247
+ // session is not kept alive by a server still logged in with it.
248
+ socket.end(toLine({ id, stopped: true }));
249
+ await this.stop();
250
+ }
251
+ else if (request.login === true) {
252
+ const client = this.#client;
253
+ socket.write(toLine(client && !this.#stale
254
+ ? { id, payload: client.live.snapshot() }
255
+ : { id, error: { code: "unavailable", message: this.#stale ? "the login went stale" : "not connected" } }));
256
+ }
257
+ else if (typeof request.opcode === "number") {
258
+ socket.write(toLine({ id, ...(await this.#forward(request.opcode, request.payload)) }));
259
+ }
260
+ else {
261
+ socket.write(toLine({ id, error: { code: "bad_request", message: "subscribe, status, login or an opcode" } }));
262
+ }
263
+ }
264
+ async #forward(opcode, payload) {
265
+ const client = this.#client;
266
+ if (!READS.has(opcode)) {
267
+ return {
268
+ error: { code: "not_allowed", message: `opcode ${opcode} is not a read; send it on your own connection` },
269
+ };
270
+ }
271
+ if (!client)
272
+ return { error: { code: "unavailable", message: "not connected" } };
273
+ try {
274
+ return { payload: await client.live.forward(opcode, (payload ?? {})) };
275
+ }
276
+ catch (error) {
277
+ if (error instanceof ProtocolError) {
278
+ return { error: { code: "refused", message: error.message, payload: error.payload } };
279
+ }
280
+ return { error: { code: "unavailable", message: error instanceof Error ? error.message : String(error) } };
281
+ }
282
+ }
283
+ }
284
+ /** 1 s, 2 s, 4 s … a minute at most — a server that hammers MAX after a drop looks like nothing MAX knows. */
285
+ const backoff = (attempt) => Math.min(60_000, 1000 * 2 ** attempt);
286
+ /** Present while a server is being started in the background, so two commands do not start two. */
287
+ export const startingPath = (store) => `${store.socketPath()}.starting`;
288
+ /** Whether something is listening on the socket — a live server, not a leftover file. */
289
+ export const answers = (path) => new Promise((resolve) => {
290
+ const probe = connect(path);
291
+ probe.once("connect", () => {
292
+ probe.destroy();
293
+ resolve(true);
294
+ });
295
+ probe.once("error", () => resolve(false));
296
+ });
297
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AACtD,OAAO,EAAE,OAAO,EAAE,YAAY,EAA4B,MAAM,UAAU,CAAA;AAC1E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE5C,OAAO,EAAE,SAAS,EAAyB,MAAM,cAAc,CAAA;AAE/D,OAAO,EAAE,UAAU,EAA0B,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAE7F,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AA2B9C,8GAA8G;AAC9G,MAAM,aAAa,GAAG,MAAM,CAAA;AAE5B,yFAAyF;AACzF,MAAM,gBAAgB,GAAG,MAAM,CAAA;AAE/B;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,SAAS;IACX,QAAQ,CAAkB;IAC1B,YAAY,GAAG,IAAI,GAAG,EAAU,CAAA;IACzC,SAAS,CAAoB;IAC7B,OAAO,CAAuB;IAC9B,KAAK,CAA4C;IACjD,MAAM,CAA2C;IACjD,QAAQ,GAAG,CAAC,CAAA;IACZ,QAAQ,GAAG,KAAK,CAAA;IAChB,gGAAgG;IAChG,MAAM,GAAG,KAAK,CAAA;IACd,QAAQ,CAA2C;IACnD,YAAY,GAAG,CAAC,CAAA;IAChB,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACrB,KAAK,CAA4C;IACjD,OAAO,CAAuC;IAC9C,kFAAkF;IACzE,IAAI,CAAe;IAE5B,YAAY,OAAyB;QACnC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,IAAI,CAAC,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;QAC/D,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,OAAO,KAAK,SAAS,CAAA;IACnC,CAAC;IAED,2FAA2F;IAC3F,KAAK,CAAC,KAAK;QACT,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAA;YACrB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAA;QACtB,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QAC5D,CAAC;QACD,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAA;QAChC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,CAAC,KAAK,GAAG,WAAW,CACtB,GAAG,EAAE;gBACH,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,IAAI,MAAM,EAAE,CAAC;oBACzE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,0BAA0B,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAA;oBAC1F,KAAK,IAAI,CAAC,IAAI,EAAE,CAAA;gBAClB,CAAC;YACH,CAAC,EACD,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CACzB,CAAA;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAa;QACtB,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAM;QACzB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;QACpB,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACzB,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACzB,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC3B,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACzB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,YAAY;YAAE,MAAM,CAAC,OAAO,EAAE,CAAA;QACxD,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAA;QACzB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;QAC1G,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QACzD,MAAM,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,CAAA;QAC3B,IAAI,CAAC,OAAO,GAAG,SAAS,CAAA;QACxB,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAA;IACvB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,QAAQ;QACZ,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAA;QACzD,IAAI,IAA2B,CAAA;QAC/B,MAAM,KAAK,GAAwC,EAAE,CAAA;QACrD,MAAM,UAAU,GAAG,CACjB,IAAI,CAAC,QAAQ,CAAC,UAAU;YACxB,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,UAAU,CAAC,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAC3F,CAAC;YACA,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBACjB,IAAI,IAAI;oBAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAA;;oBAC1D,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAA;YACtD,CAAC;YACD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBACjB,IAAI,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC,OAAO;oBAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YACtD,CAAC;SACF,CAAC,CAAA;QACF,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;YAC3B,KAAK;YACL,UAAU;YACV,SAAS,EAAE,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI;YACxB,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3B,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9B,CAAC,CAAA;QACF,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,OAAO,EAAE,CAAA;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,4FAA4F;YAC5F,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;YACpB,MAAM,KAAK,CAAA;QACb,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAA;QAC7B,IAAI,GAAG,MAAM,CAAA;QACb,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;QACrB,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAA;QACjB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC9B,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACzB,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;YAC5B,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QACpC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,IAAI,aAAa,CAAC,CAAA;QAC9C,IAAI,QAAQ;YAAE,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;;YAC/C,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;QACxF,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,KAAK;YAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9E,CAAC;IAED,OAAO,CAAC,MAAiB,EAAE,MAAc,EAAE,OAAgC;QACzE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC;YAAE,IAAI,CAAC,UAAU,EAAE,CAAA;QAC1D,MAAM,CAAC,IAAI;aACR,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC;aACxB,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,IAAI,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;aAC5E,KAAK,CAAC,CAAC,KAAY,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,uCAAuC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;IACxG,CAAC;IAED;;;OAGG;IACH,UAAU;QACR,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;QAClB,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAM;QAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,IAAI,gBAAgB,CAAA;QAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;QAChE,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,IAAI,CAAC,QAAQ,EAAE;iBACZ,KAAK,CAAC,CAAC,KAAY,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,2BAA2B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;iBACvF,OAAO,CAAC,GAAG,EAAE;gBACZ,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAA;YAC3B,CAAC,CAAC,CAAA;QACN,CAAC,EAAE,IAAI,CAAC,CAAA;IACV,CAAC;IAED,KAAK,CAAC,KAAY;QAChB,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAA;QAC3B,IAAI,CAAC,OAAO,GAAG,SAAS,CAAA;QACxB,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC/B,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAM;QAEzB,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;QACpF,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAA;IAC7B,CAAC;IAED,eAAe,CAAC,KAAY;QAC1B,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,IAAI,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACnE,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAA;QAClB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,0BAA0B,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAA;QACxF,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC,OAAc,EAAE,EAAE;gBACvC,0EAA0E;gBAC1E,IAAI,OAAO,YAAY,QAAQ,IAAI,OAAO,CAAC,IAAI,KAAK,sBAAsB;oBAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;;oBACzF,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAA;YACpC,CAAC,CAAC,CAAA;QACJ,CAAC,EAAE,IAAI,CAAC,CAAA;IACV,CAAC;IAED,UAAU,CAAC,KAAkB;QAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;QAC1B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,YAAY;YAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAC5D,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,UAAU,EAAE,CAAA;QAC7C,IAAI,MAAM,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,4CAA4C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAA;QACpH,CAAC;QACD,oEAAoE;QACpE,MAAM,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QAC7B,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;QAE1D,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;QAC9D,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;YAC9B,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAA;QACxC,CAAC,CAAC,CAAA;QACF,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QACtB,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAA;IAC3B,CAAC;IAED,MAAM,CAAC,MAAc;QACnB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;QAC1D,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACtB,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;YAChC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC5B,CAAC,CAAC,CAAA;QACF,MAAM,CAAC,EAAE,CACP,MAAM,EACN,UAAU,CAAC,CAAC,IAAI,EAAE,EAAE;YAClB,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAA;QAC3D,CAAC,CAAC,CACH,CAAA;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,MAAc,EAAE,IAAY;QACzC,IAAI,OAAgC,CAAA;QACpC,IAAI,CAAC;YACH,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,0BAA0B,EAAE,EAAE,CAAC,CAAC,CAAA;YAC7F,OAAM;QACR,CAAC;QACD,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAA;QAC3F,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAE1B,IAAI,OAAO,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;YAC/B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YAC7B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;QAC9B,CAAC;aAAM,IAAI,OAAO,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;QAC9B,CAAC;aAAM,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YACjC,0FAA0F;YAC1F,iEAAiE;YACjE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;YACzC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAA;QACnB,CAAC;aAAM,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YAClC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAA;YAC3B,MAAM,CAAC,KAAK,CACV,MAAM,CACJ,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM;gBACpB,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE;gBACzC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,eAAe,EAAE,EAAE,CAC5G,CACF,CAAA;QACH,CAAC;aAAM,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC9C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QACzF,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,uCAAuC,EAAE,EAAE,CAAC,CAAC,CAAA;QAChH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,MAAc,EAAE,OAAgB;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAA;QAC3B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACvB,OAAO;gBACL,KAAK,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,MAAM,gDAAgD,EAAE;aAC1G,CAAA;QACH,CAAC;QACD,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,eAAe,EAAE,EAAE,CAAA;QAChF,IAAI,CAAC;YACH,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,OAAO,IAAI,EAAE,CAA4B,CAAC,EAAE,CAAA;QACnG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,aAAa,EAAE,CAAC;gBACnC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,CAAA;YACvF,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAA;QAC5G,CAAC;IACH,CAAC;CACF;AAED,8GAA8G;AAC9G,MAAM,OAAO,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,GAAG,CAAC,IAAI,OAAO,CAAC,CAAA;AAElF,mGAAmG;AACnG,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAmB,EAAU,EAAE,CAAC,GAAG,KAAK,CAAC,UAAU,EAAE,WAAW,CAAA;AAE7F,yFAAyF;AACzF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAY,EAAoB,EAAE,CACxD,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;IACtB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3B,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE;QACzB,KAAK,CAAC,OAAO,EAAE,CAAA;QACf,OAAO,CAAC,IAAI,CAAC,CAAA;IACf,CAAC,CAAC,CAAA;IACF,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;AAC3C,CAAC,CAAC,CAAA"}
@@ -0,0 +1,12 @@
1
+ import type { SessionStore } from "../session/store.js";
2
+ /** A server a command started stops after this long unused. */
3
+ export declare const IDLE_MS: number;
4
+ /**
5
+ * Starts `max serve` for this profile in the background, detached, and returns at once — the
6
+ * command that asked goes on with its own connection and the next one finds the server.
7
+ *
8
+ * Its stderr goes to `<state>/profiles/<profile>.serve.log`, mode 600: nobody is watching a
9
+ * terminal for it, and that file is where a login that failed says so.
10
+ */
11
+ export declare const startInBackground: (store: SessionStore, entry?: string | undefined) => boolean;
12
+ //# sourceMappingURL=start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/server/start.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAGvD,+DAA+D;AAC/D,eAAO,MAAM,OAAO,QAAc,CAAA;AAKlC;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,YAAY,EAAE,0BAAuB,KAAG,OAuBhF,CAAA"}
@@ -0,0 +1,41 @@
1
+ import { spawn } from "node:child_process";
2
+ import { closeSync, mkdirSync, openSync, rmSync, statSync } from "node:fs";
3
+ import { dirname } from "node:path";
4
+ import { startingPath } from "./server.js";
5
+ /** A server a command started stops after this long unused. */
6
+ export const IDLE_MS = 15 * 60_000;
7
+ /** A start that has not listened by now crashed; the next command may try again. */
8
+ const START_GRACE_MS = 30_000;
9
+ /**
10
+ * Starts `max serve` for this profile in the background, detached, and returns at once — the
11
+ * command that asked goes on with its own connection and the next one finds the server.
12
+ *
13
+ * Its stderr goes to `<state>/profiles/<profile>.serve.log`, mode 600: nobody is watching a
14
+ * terminal for it, and that file is where a login that failed says so.
15
+ */
16
+ export const startInBackground = (store, entry = process.argv[1]) => {
17
+ if (!entry || store.readToken() === undefined)
18
+ return false;
19
+ const lock = startingPath(store);
20
+ mkdirSync(dirname(lock), { recursive: true, mode: 0o700 });
21
+ try {
22
+ closeSync(openSync(lock, "wx", 0o600));
23
+ }
24
+ catch {
25
+ const since = statSync(lock, { throwIfNoEntry: false })?.mtimeMs ?? 0;
26
+ if (Date.now() - since <= START_GRACE_MS)
27
+ return false;
28
+ rmSync(lock, { force: true });
29
+ closeSync(openSync(lock, "wx", 0o600));
30
+ }
31
+ const log = openSync(`${store.socketPath().replace(/\.sock$/, "")}.serve.log`, "a", 0o600);
32
+ const child = spawn(process.execPath, [entry, "--no-record", "serve", "--idle", `${IDLE_MS / 60_000}m`], {
33
+ detached: true,
34
+ stdio: ["ignore", "ignore", log],
35
+ env: { ...process.env, MAX_PROFILE: store.profile },
36
+ });
37
+ child.unref();
38
+ closeSync(log);
39
+ return true;
40
+ };
41
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/server/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAC1E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C,+DAA+D;AAC/D,MAAM,CAAC,MAAM,OAAO,GAAG,EAAE,GAAG,MAAM,CAAA;AAElC,oFAAoF;AACpF,MAAM,cAAc,GAAG,MAAM,CAAA;AAE7B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAmB,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAW,EAAE;IACzF,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,EAAE,KAAK,SAAS;QAAE,OAAO,KAAK,CAAA;IAE3D,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;IAChC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IAC1D,IAAI,CAAC;QACH,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAA;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,IAAI,CAAC,CAAA;QACrE,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,cAAc;YAAE,OAAO,KAAK,CAAA;QACtD,MAAM,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QAC7B,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAA;IACxC,CAAC;IAED,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;IAC1F,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,OAAO,GAAG,MAAM,GAAG,CAAC,EAAE;QACvG,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,CAAC;QAChC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,CAAC,OAAO,EAAE;KACpD,CAAC,CAAA;IACF,KAAK,CAAC,KAAK,EAAE,CAAA;IACb,SAAS,CAAC,GAAG,CAAC,CAAA;IACd,OAAO,IAAI,CAAA;AACb,CAAC,CAAA"}
@@ -0,0 +1,9 @@
1
+ import type { ServerEvent } from "./server.js";
2
+ /**
3
+ * Listens to a running `max serve` until it goes away or `signal` fires.
4
+ *
5
+ * No server is an error that names the command to start one — starting it silently would leave a
6
+ * long-lived connection nobody asked for.
7
+ */
8
+ export declare const subscribe: (path: string, profile: string, onEvent: (event: ServerEvent) => void, signal?: AbortSignal) => Promise<void>;
9
+ //# sourceMappingURL=subscribe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscribe.d.ts","sourceRoot":"","sources":["../../src/server/subscribe.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GACpB,MAAM,MAAM,EACZ,SAAS,MAAM,EACf,SAAS,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,EACrC,SAAS,WAAW,KACnB,OAAO,CAAC,IAAI,CAmBX,CAAA"}
@@ -0,0 +1,26 @@
1
+ import { connect } from "node:net";
2
+ import { CliError } from "@leemour/cli-core";
3
+ import { asFirstWord } from "../profile.js";
4
+ import { fromLine, lineReader } from "./lines.js";
5
+ /**
6
+ * Listens to a running `max serve` until it goes away or `signal` fires.
7
+ *
8
+ * No server is an error that names the command to start one — starting it silently would leave a
9
+ * long-lived connection nobody asked for.
10
+ */
11
+ export const subscribe = (path, profile, onEvent, signal) => new Promise((resolve, reject) => {
12
+ const socket = connect(path);
13
+ signal?.addEventListener("abort", () => socket.end(), { once: true });
14
+ socket.once("connect", () => socket.write(`${JSON.stringify({ subscribe: true })}\n`));
15
+ socket.on("data", lineReader((line) => onEvent(fromLine(line))));
16
+ socket.once("error", (error) => {
17
+ if (error.code === "ENOENT" || error.code === "ECONNREFUSED") {
18
+ const command = `max ${asFirstWord(profile)}serve`;
19
+ reject(new CliError("not_found", `no server is running for profile "${profile}" — start one with \`${command}\``));
20
+ }
21
+ else
22
+ reject(error);
23
+ });
24
+ socket.once("close", () => resolve());
25
+ });
26
+ //# sourceMappingURL=subscribe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscribe.js","sourceRoot":"","sources":["../../src/server/subscribe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAGjD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,IAAY,EACZ,OAAe,EACf,OAAqC,EACrC,MAAoB,EACL,EAAE,CACjB,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IAC9B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE5B,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;IACrE,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;IACtF,MAAM,CAAC,EAAE,CACP,MAAM,EACN,UAAU,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA2B,CAAC,CAAC,CACxE,CAAA;IACD,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAA4B,EAAE,EAAE;QACpD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YAC7D,MAAM,OAAO,GAAG,OAAO,WAAW,CAAC,OAAO,CAAC,OAAO,CAAA;YAClD,MAAM,CACJ,IAAI,QAAQ,CAAC,WAAW,EAAE,qCAAqC,OAAO,wBAAwB,OAAO,IAAI,CAAC,CAC3G,CAAA;QACH,CAAC;;YAAM,MAAM,CAAC,KAAK,CAAC,CAAA;IACtB,CAAC,CAAC,CAAA;IACF,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAA;AACvC,CAAC,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"adopt.d.ts","sourceRoot":"","sources":["../../src/session/adopt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,GAAU,QAAQ,SAAS,EAAE,OAAO,YAAY,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,IAAI,CASpG,CAAA"}
1
+ {"version":3,"file":"adopt.d.ts","sourceRoot":"","sources":["../../src/session/adopt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,GAAU,QAAQ,SAAS,EAAE,OAAO,YAAY,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,IAAI,CAUpG,CAAA"}
@@ -17,13 +17,14 @@
17
17
  * cannot be driven by a test — and this ordering is too expensive to hold on trust.
18
18
  */
19
19
  export const adoptToken = async (client, store, token) => {
20
+ const before = store.readToken();
20
21
  await client.connect({ token });
21
- // ⚠ **Only if the login did not already leave a better one.** MAX answers every login with a
22
- // fresh token and `connect` now keeps it (`MAX-11`); writing the pasted one here unconditionally
23
- // would replace that with the credential the person copied out of a browser, which is the older
24
- // of the two. The check also covers the case where the keyring write failed inside `connect`:
25
- // then there is nothing stored, and what was pasted is better than nothing.
26
- if (store.readToken() === undefined)
22
+ // ⚠ **Only if the login did not already leave a better one.** MAX answers a login with a fresh
23
+ // token when the one presented has aged, and `connect` keeps it (`MAX-11`); overwriting that here
24
+ // would put back the older credential. Comparing with what was stored before, rather than asking
25
+ // whether anything is stored, is what lets a new login replace an old session at all — until
26
+ // 2026-09-24 a profile that already held a token kept it, and the command still said "stored".
27
+ if (store.readToken() === before)
27
28
  store.writeToken(token);
28
29
  };
29
30
  //# sourceMappingURL=adopt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"adopt.js","sourceRoot":"","sources":["../../src/session/adopt.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,MAAiB,EAAE,KAAmB,EAAE,KAAa,EAAiB,EAAE;IACvG,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;IAE/B,6FAA6F;IAC7F,iGAAiG;IACjG,gGAAgG;IAChG,8FAA8F;IAC9F,4EAA4E;IAC5E,IAAI,KAAK,CAAC,SAAS,EAAE,KAAK,SAAS;QAAE,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;AAC9D,CAAC,CAAA"}
1
+ {"version":3,"file":"adopt.js","sourceRoot":"","sources":["../../src/session/adopt.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,MAAiB,EAAE,KAAmB,EAAE,KAAa,EAAiB,EAAE;IACvG,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,EAAE,CAAA;IAChC,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;IAE/B,+FAA+F;IAC/F,kGAAkG;IAClG,iGAAiG;IACjG,6FAA6F;IAC7F,+FAA+F;IAC/F,IAAI,KAAK,CAAC,SAAS,EAAE,KAAK,MAAM;QAAE,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;AAC3D,CAAC,CAAA"}
@@ -0,0 +1,55 @@
1
+ import { type ChildProcess } from "node:child_process";
2
+ import type { Closeable } from "../deadline.js";
3
+ /**
4
+ * What `session start` needs from a browser. Injected in tests, which must never open a window on
5
+ * the owner's desktop — the real ones refuse inside the test sandbox.
6
+ */
7
+ export interface BrowserDoors {
8
+ /** Shows a page in whatever browser the system opens links with. */
9
+ open: (url: string) => Promise<void>;
10
+ /** Opens web.max.ru in a Chromium-family browser and waits for the page to be logged in. */
11
+ chromiumToken: (options: {
12
+ track: (closeable: Closeable) => void;
13
+ waitMs: number;
14
+ }) => Promise<string>;
15
+ }
16
+ export declare const realBrowser: BrowserDoors;
17
+ /**
18
+ * The QR page, served from `127.0.0.1` rather than written to a file: a browser installed as a
19
+ * snap cannot read our temporary directory, and a file would leave the link on disk. The path is
20
+ * random, so another local user guessing the port finds nothing.
21
+ */
22
+ export declare const serveQrPage: (link: string) => Promise<{
23
+ url: string;
24
+ } & Closeable>;
25
+ export declare const openUrl: (url: string) => Promise<void>;
26
+ /**
27
+ * Chrome, Chromium, Edge or Brave — any browser that speaks the DevTools protocol. `MAX_BROWSER`
28
+ * names another. A snap build is skipped: it keeps its own `/tmp`, so the profile we hand it would
29
+ * land where we cannot delete it.
30
+ */
31
+ export declare const findChromium: () => string | undefined;
32
+ /**
33
+ * web.max.ru logs itself in — it asks MAX for the QR code, or sends the SMS — in a real browser with
34
+ * a profile of its own, and we read the token it stores once it has one. MAX sees its own web
35
+ * client do the login, not our socket.
36
+ *
37
+ * ⚠ The profile holds a live session, so it is deleted on every way out: success, a closed window,
38
+ * `--timeout`, Ctrl-C.
39
+ */
40
+ export declare const tokenFromChromium: ({ track, waitMs, }: {
41
+ track: (closeable: Closeable) => void;
42
+ waitMs: number;
43
+ }) => Promise<string>;
44
+ export declare class ChromiumSession implements Closeable {
45
+ #private;
46
+ constructor(child: ChildProcess, profile: string, graceMs?: number);
47
+ waitForToken(waitMs: number): Promise<string>;
48
+ close(): Promise<void>;
49
+ }
50
+ /**
51
+ * The stored value is JSON holding the token, or the token itself — which one is not measured yet.
52
+ * Either way nothing here prints it.
53
+ */
54
+ export declare const tokenIn: (stored: string) => string | undefined;
55
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/session/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAS,MAAM,oBAAoB,CAAA;AAW7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE/C;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,oEAAoE;IACpE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACpC,4FAA4F;IAC5F,aAAa,EAAE,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CACvG;AAED,eAAO,MAAM,WAAW,EAAE,YAGzB,CAAA;AAKD;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAU,MAAM,MAAM,KAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAkCnF,CAAA;AASD,eAAO,MAAM,OAAO,GAAU,KAAK,MAAM,KAAG,OAAO,CAAC,IAAI,CAmBvD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,QAAO,MAAM,GAAG,SA0CxC,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,GAAU,oBAGrC;IACD,KAAK,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,CAAA;IACrC,MAAM,EAAE,MAAM,CAAA;CACf,KAAG,OAAO,CAAC,MAAM,CA4BjB,CAAA;AAED,qBAAa,eAAgB,YAAW,SAAS;;gBASnC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,SAAQ;IAW3D,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBnD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CA0CvB;AAuED;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAI,QAAQ,MAAM,KAAG,MAAM,GAAG,SAWjD,CAAA"}