@mega-yfue/eufy-sdk 0.3.0-beta.3 → 0.3.0-beta.5

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.
@@ -91,8 +91,9 @@ export declare class SessionExpiredError extends Error {
91
91
  /**
92
92
  * Whether this rejection landed inside that bar — a token replaced recently and rejected again since.
93
93
  *
94
- * It says the session is being DISPLACED rather than expiring: something else is signing in on this
95
- * account, and replacing the token again only trades one login for another.
94
+ * That is the shape displacement by another client signed in on this account has, where replacing the
95
+ * token again only trades one login for another. It is not proof of one, since a cloud refusing to
96
+ * re-issue the session looks the same.
96
97
  */
97
98
  readonly contended: boolean;
98
99
  constructor(message: string, opts?: {
@@ -212,6 +213,8 @@ export declare class MegaHttpClient {
212
213
  private sessionKey?;
213
214
  /** Per-host ECDH session keys for non-mega gateways (e.g. eufylife) keyed by host. */
214
215
  private readonly sessionKeys;
216
+ /** The in-flight key exchanges, by host and the token they carry — see {@link ensureSessionKey}. */
217
+ private readonly keyExchanges;
215
218
  /**
216
219
  * The held credential. `userId` is the login reply's `ap_cloud_user_id` where it has one — the Anker
217
220
  * Passport cloud's id — while `accountUserId` is the eufy account's own `user_id`.
@@ -318,6 +321,8 @@ export declare class MegaHttpClient {
318
321
  * so it MUST be reused (don't re-exchange after login).
319
322
  */
320
323
  ensureSessionKey(targetHost?: string): Promise<SessionEntry>;
324
+ /** One key exchange against `host`, installed as that host's key. */
325
+ private exchangeSessionKey;
321
326
  /**
322
327
  * Signed + encrypted POST. Content-type auto-falls-back (text/plain ↔ json).
323
328
  *
@@ -523,8 +528,8 @@ export declare class MegaHttpClient {
523
528
  * like the same device — and the cloud keeps one session per device. Each finds its token rejected, replaces
524
529
  * it, and evicts the other: an unbounded login war, silent, and repeated logins are exactly what makes an
525
530
  * account start demanding captchas. The first replacement is immediate, because a token displaced once is
526
- * the ordinary case; a second one soon after is evidence of contention rather than expiry, so the wait grows
527
- * and a caller is told the honest reason instead of being served a fight.
531
+ * the ordinary case; a second one soon after has the shape of contention rather than expiry, so the wait grows
532
+ * and a caller is told what was seen instead of being served a fight.
528
533
  */
529
534
  private recoveryDue;
530
535
  /**
@@ -10,6 +10,10 @@ import type { FcmCredentials, PushEvent, RawPushMessage } from "./types.js";
10
10
  import { type Logger } from "../../core/logger.js";
11
11
  /**
12
12
  * Normalises a decoded eufy envelope without consulting device semantics; semantic event names remain unset.
13
+ *
14
+ * The detail (`event_type`, `pic_url`, `cipher`) is read from the deepest level of
15
+ * `payloadLevels`; identity (`device_sn`, `station_sn`) is gathered from every level, deepest
16
+ * first, so a serial is found whichever level the push carries it on.
13
17
  * @internal
14
18
  */
15
19
  export declare function normalizePushEvent(raw: RawPushMessage): PushEvent;
@@ -55,6 +59,13 @@ export declare class PushClient extends EventEmitter {
55
59
  * {@link MAX_LOGIN_FAILURES} consecutive attempts (creds genuinely stale) is it emitted as `error`.
56
60
  */
57
61
  private onLoginError;
62
+ /**
63
+ * Decode one MCS `DataMessageStanza` into a {@link RawPushMessage} and the normalised event.
64
+ *
65
+ * `payload` carries the whole app_data envelope, with its `payload` entry (base64 of NUL-terminated
66
+ * JSON) parsed in place: the envelope's own keys, `device_sn` and `station_sn` among them, sit beside
67
+ * that entry.
68
+ */
58
69
  private handleDataMessage;
59
70
  private startHeartbeat;
60
71
  private stopHeartbeat;
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * eufy FCM push payload types.
3
3
  *
4
- * A push arrives as an MCS DataMessageStanza whose `app_data` has a `payload`
5
- * entry = base64( NUL-terminated JSON ). That JSON is the EufyPushMessage; its
6
- * nested `payload` is device-type specific. The v6 app enriches these with AI
7
- * detection fields (person/vehicle/pet/package/faces/crops/short video) — see
8
- * PushEnrichment.
4
+ * A push arrives as an MCS DataMessageStanza whose `app_data` entries make up the
5
+ * EufyPushMessage envelope. Its `payload` entry is base64( NUL-terminated JSON ), the
6
+ * device-type specific detail, which may itself nest a further `payload`. The v6 app
7
+ * enriches these with AI detection fields (person/vehicle/pet/package/faces/crops/short
8
+ * video) — see PushEnrichment.
9
9
  */
10
10
  /**
11
11
  * Raw MCS frame: a tag + the decoded protobuf object.
@@ -31,10 +31,10 @@ export interface RawPushMessage {
31
31
  persistentId?: string;
32
32
  ttl?: number;
33
33
  sent?: string;
34
- /** The decoded eufy payload (the `payload` app_data entry, JSON-parsed). */
34
+ /** The eufy envelope, as `EufyPushMessage` describes it. */
35
35
  payload: EufyPushMessage;
36
36
  }
37
- /** The eufy JSON envelope inside the push. */
37
+ /** The eufy envelope: the push's `app_data` entries, with the `payload` entry JSON-parsed in place. */
38
38
  export interface EufyPushMessage {
39
39
  type?: string | number;
40
40
  title?: string;
@@ -45,7 +45,7 @@ export interface EufyPushMessage {
45
45
  push_time?: string;
46
46
  doorbell?: string;
47
47
  "google.c.sender.id"?: string;
48
- /** Device-type specific body (often a JSON string that we further parse). */
48
+ /** The decoded `payload` entry: device-type specific detail, which may nest a further `payload`. */
49
49
  payload?: PushPayload;
50
50
  [k: string]: unknown;
51
51
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mega-yfue/eufy-sdk",
3
- "version": "0.3.0-beta.3",
3
+ "version": "0.3.0-beta.5",
4
4
  "description": "One typed TypeScript client for the Anker eufy v6 cloud — capability-driven devices, realtime events over P2P/MQTT/push, and live media",
5
5
  "license": "Apache-2.0",
6
6
  "author": "mega-yfue",