@spacemolt/lib 12.1.0 → 12.2.1

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/README.md CHANGED
@@ -95,6 +95,19 @@ await account.mutate('spacemolt', 'jump', { id: 'sol' });
95
95
  await account.send('spacemolt', 'jump', { id: 'sol' }); // auto-routes query/mutation
96
96
  ```
97
97
 
98
+ Every one of those takes an optional trailing `requestId`. The server echoes it
99
+ back on the response, so you can correlate your own in-flight requests:
100
+
101
+ ```ts
102
+ await account.commands.spacemolt.jump({ id: 'sol' }, 'my-id-1');
103
+ await account.query('spacemolt', 'get_status', undefined, 'my-id-2');
104
+ await account.mutate('spacemolt', 'mine', undefined, undefined, 'my-id-3');
105
+ ```
106
+
107
+ Omit it and the library picks one. Give each request a new id: an id that is
108
+ already in flight is refused with a `duplicate_request_id` error, and an id you
109
+ reuse after its request timed out can settle on the wrong response.
110
+
98
111
  ### Local state cache
99
112
 
100
113
  Seeded from `get_status` after auth and updated from the delta on every
package/dist/account.d.ts CHANGED
@@ -160,6 +160,8 @@ export declare class Account {
160
160
  private subscribedMarketBaseId;
161
161
  private observationSubscribedState;
162
162
  private observationActiveScanState;
163
+ /** Invalidates an in-flight reconciliation whenever a newer cache update arrives. */
164
+ private stateRevision;
163
165
  private subscribedObservationPoiId;
164
166
  private readonly reconnectedListeners;
165
167
  private readonly reconnectingListeners;
@@ -256,7 +258,7 @@ export declare class Account {
256
258
  * to take long, so a response that never arrives (the server silently
257
259
  * drops it rather than erroring) fails cleanly instead of hanging forever.
258
260
  */
259
- query(tool: string, action: string, payload?: Record<string, unknown>): Promise<QueryResult>;
261
+ query(tool: string, action: string, payload?: Record<string, unknown>, requestId?: string): Promise<QueryResult>;
260
262
  /**
261
263
  * Run a mutation; resolves when the action executes on a later tick (after
262
264
  * the immediate pending ack). `onAck` fires when the pending ack arrives.
@@ -273,7 +275,7 @@ export declare class Account {
273
275
  * every other mutation — `mine`, `craft`, etc. — settles within the tick it
274
276
  * was queued on and gets the much shorter `fastMutationTimeoutMs`.
275
277
  */
276
- mutate(tool: string, action: string, payload?: Record<string, unknown>, onAck?: (ack: MutationAck) => void): Promise<MutationResult>;
278
+ mutate(tool: string, action: string, payload?: Record<string, unknown>, onAck?: (ack: MutationAck) => void, requestId?: string): Promise<MutationResult>;
277
279
  /**
278
280
  * Waits for a mutation's outcome with two-phase timeout protection. The
279
281
  * pending ack (`result` frame) is a synchronous validation step with no
@@ -292,7 +294,7 @@ export declare class Account {
292
294
  * Run a command, dispatching to `query`/`mutate` based on the spec's
293
295
  * `x-is-mutation` classification. Unknown commands are treated as queries.
294
296
  */
295
- send(tool: string, action: string, payload?: Record<string, unknown>): Promise<QueryResult | MutationResult>;
297
+ send(tool: string, action: string, payload?: Record<string, unknown>, requestId?: string): Promise<QueryResult | MutationResult>;
296
298
  /**
297
299
  * Listen for a specific server push by msg_type. The handler receives the
298
300
  * typed payload for published notification types, or a loosely-typed object
@@ -374,6 +376,22 @@ export declare class Account {
374
376
  * after every state update that could carry a `location` change.
375
377
  */
376
378
  private checkSubscriptionsAgainstLocation;
379
+ /**
380
+ * Fleet followers do not submit the movement mutation themselves, so their
381
+ * arrival is delivered as a plain `ok` push rather than an `action_result`
382
+ * carrying a state delta. Bridge the location data present on those pushes
383
+ * into the cache. Fleet docking is the one exception: its push only contains
384
+ * the station's display name, not the canonical base ID used by `docked_at`,
385
+ * so refresh the canonical snapshot instead of caching the wrong identifier.
386
+ */
387
+ private applyFleetMovementPush;
388
+ /**
389
+ * Fleet movement pushes omit follower fuel and skill deltas, while docking
390
+ * omits the canonical base ID. Reconcile those fields from one authoritative
391
+ * snapshot. A newer movement push invalidates an older in-flight query so a
392
+ * delayed dock/arrival snapshot cannot move the cache backwards.
393
+ */
394
+ private reconcileFleetState;
377
395
  /** Close the connection deliberately. Suppresses auto-reconnect. */
378
396
  close(): void;
379
397
  /** Fired after a successful reconnect + re-auth. Returns an unsubscribe function. */
@@ -391,6 +409,18 @@ export declare class Account {
391
409
  private beginAuth;
392
410
  private sendFrame;
393
411
  private nextRequestId;
412
+ /**
413
+ * Pick the `request_id` for one frame. A caller-supplied id is echoed by the
414
+ * server unchanged, which is the point — it lets the caller correlate its own
415
+ * in-flight requests. An empty id is treated as no id, because the server
416
+ * drops falsy ids and the request would then hang until it timed out.
417
+ *
418
+ * A caller-supplied id must be unique for the life of the connection, not
419
+ * only while it is in flight. Reusing a live id is refused here. Reusing an
420
+ * id whose request timed out is not detected, and a late frame for the first
421
+ * request then settles the second one with the wrong outcome.
422
+ */
423
+ private claimRequestId;
394
424
  private routeFrame;
395
425
  private warnMalformedFrame;
396
426
  private handleClose;