@spacemolt/lib 12.2.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/dist/account.d.ts +18 -0
- package/dist/index.js +125 -0
- package/package.json +1 -1
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;
|
|
@@ -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. */
|
package/dist/index.js
CHANGED
|
@@ -4027,6 +4027,7 @@ class Account {
|
|
|
4027
4027
|
subscribedMarketBaseId;
|
|
4028
4028
|
observationSubscribedState = false;
|
|
4029
4029
|
observationActiveScanState = false;
|
|
4030
|
+
stateRevision = 0;
|
|
4030
4031
|
subscribedObservationPoiId;
|
|
4031
4032
|
reconnectedListeners = new Set;
|
|
4032
4033
|
reconnectingListeners = new Set;
|
|
@@ -4195,6 +4196,8 @@ class Account {
|
|
|
4195
4196
|
const result = await this.commands.spacemolt.get_status();
|
|
4196
4197
|
const snapshot = requireStructuredContent(result, "spacemolt/get_status");
|
|
4197
4198
|
const changed = this.cache.seed(snapshot);
|
|
4199
|
+
if (changed.length)
|
|
4200
|
+
this.stateRevision++;
|
|
4198
4201
|
if (changed.includes("location"))
|
|
4199
4202
|
this.checkSubscriptionsAgainstLocation();
|
|
4200
4203
|
if (changed.length)
|
|
@@ -4331,6 +4334,8 @@ class Account {
|
|
|
4331
4334
|
nearby_players: nearbyPlayers,
|
|
4332
4335
|
nearby_player_count: view.nearby.size
|
|
4333
4336
|
});
|
|
4337
|
+
if (changed.length)
|
|
4338
|
+
this.stateRevision++;
|
|
4334
4339
|
if (changed.length)
|
|
4335
4340
|
this.emitStateChange(changed);
|
|
4336
4341
|
}
|
|
@@ -4349,6 +4354,123 @@ class Account {
|
|
|
4349
4354
|
this.subscribedObservationPoiId = undefined;
|
|
4350
4355
|
}
|
|
4351
4356
|
}
|
|
4357
|
+
applyFleetMovementPush(frame) {
|
|
4358
|
+
if (frame.type !== "ok" || !isRecord(frame.payload) || typeof frame.payload.action !== "string")
|
|
4359
|
+
return;
|
|
4360
|
+
const payload = frame.payload;
|
|
4361
|
+
let changed = [];
|
|
4362
|
+
let reconcile = false;
|
|
4363
|
+
const currentLocation = this.cache.location;
|
|
4364
|
+
const currentSystem = {
|
|
4365
|
+
connections: currentLocation?.connections,
|
|
4366
|
+
empire: currentLocation?.empire,
|
|
4367
|
+
security_status: currentLocation?.security_status,
|
|
4368
|
+
system_id: currentLocation?.system_id,
|
|
4369
|
+
system_name: currentLocation?.system_name
|
|
4370
|
+
};
|
|
4371
|
+
switch (payload.action) {
|
|
4372
|
+
case "fleet_jump": {
|
|
4373
|
+
if (typeof payload.destination !== "string" || typeof payload.arrival_tick !== "number") {
|
|
4374
|
+
this.warnMalformedFrame(frame);
|
|
4375
|
+
return;
|
|
4376
|
+
}
|
|
4377
|
+
changed = this.cache.applyDelta({
|
|
4378
|
+
location: {
|
|
4379
|
+
in_transit: true,
|
|
4380
|
+
transit_arrival_tick: payload.arrival_tick,
|
|
4381
|
+
transit_dest_system_id: payload.destination,
|
|
4382
|
+
transit_type: "jump"
|
|
4383
|
+
}
|
|
4384
|
+
});
|
|
4385
|
+
reconcile = true;
|
|
4386
|
+
break;
|
|
4387
|
+
}
|
|
4388
|
+
case "jumped":
|
|
4389
|
+
case "pathfinder_arrival": {
|
|
4390
|
+
if (typeof payload.system_id !== "string" || typeof payload.system !== "string") {
|
|
4391
|
+
this.warnMalformedFrame(frame);
|
|
4392
|
+
return;
|
|
4393
|
+
}
|
|
4394
|
+
changed = this.cache.applyDelta({
|
|
4395
|
+
location: {
|
|
4396
|
+
in_transit: false,
|
|
4397
|
+
poi_id: typeof payload.poi === "string" ? payload.poi : undefined,
|
|
4398
|
+
system_id: payload.system_id,
|
|
4399
|
+
system_name: payload.system
|
|
4400
|
+
}
|
|
4401
|
+
});
|
|
4402
|
+
reconcile = true;
|
|
4403
|
+
break;
|
|
4404
|
+
}
|
|
4405
|
+
case "fleet_travel": {
|
|
4406
|
+
if (typeof payload.destination !== "string" || typeof payload.arrival_tick !== "number") {
|
|
4407
|
+
this.warnMalformedFrame(frame);
|
|
4408
|
+
return;
|
|
4409
|
+
}
|
|
4410
|
+
changed = this.cache.applyDelta({
|
|
4411
|
+
location: {
|
|
4412
|
+
...currentSystem,
|
|
4413
|
+
in_transit: true,
|
|
4414
|
+
transit_arrival_tick: payload.arrival_tick,
|
|
4415
|
+
transit_dest_poi_id: payload.destination,
|
|
4416
|
+
transit_type: "travel"
|
|
4417
|
+
}
|
|
4418
|
+
});
|
|
4419
|
+
reconcile = true;
|
|
4420
|
+
break;
|
|
4421
|
+
}
|
|
4422
|
+
case "arrived": {
|
|
4423
|
+
if (typeof payload.poi_id !== "string" || typeof payload.poi !== "string") {
|
|
4424
|
+
this.warnMalformedFrame(frame);
|
|
4425
|
+
return;
|
|
4426
|
+
}
|
|
4427
|
+
changed = this.cache.applyDelta({
|
|
4428
|
+
location: {
|
|
4429
|
+
...currentSystem,
|
|
4430
|
+
in_transit: false,
|
|
4431
|
+
poi_id: payload.poi_id,
|
|
4432
|
+
poi_name: payload.poi
|
|
4433
|
+
}
|
|
4434
|
+
});
|
|
4435
|
+
reconcile = true;
|
|
4436
|
+
break;
|
|
4437
|
+
}
|
|
4438
|
+
case "fleet_undock":
|
|
4439
|
+
changed = currentLocation ? this.cache.patchSection("location", { docked_at: undefined }) : this.cache.applyDelta({ location: {} });
|
|
4440
|
+
break;
|
|
4441
|
+
case "fleet_dock":
|
|
4442
|
+
reconcile = true;
|
|
4443
|
+
break;
|
|
4444
|
+
default:
|
|
4445
|
+
return;
|
|
4446
|
+
}
|
|
4447
|
+
const revision = ++this.stateRevision;
|
|
4448
|
+
if (changed.includes("location"))
|
|
4449
|
+
this.checkSubscriptionsAgainstLocation();
|
|
4450
|
+
if (changed.length)
|
|
4451
|
+
this.emitStateChange(changed);
|
|
4452
|
+
if (reconcile)
|
|
4453
|
+
this.reconcileFleetState(revision, payload.action);
|
|
4454
|
+
}
|
|
4455
|
+
async reconcileFleetState(revision, action) {
|
|
4456
|
+
try {
|
|
4457
|
+
const result = await this.commands.spacemolt.get_status();
|
|
4458
|
+
const snapshot = requireStructuredContent(result, "spacemolt/get_status");
|
|
4459
|
+
if (revision !== this.stateRevision)
|
|
4460
|
+
return;
|
|
4461
|
+
const changed = this.cache.seed(snapshot);
|
|
4462
|
+
if (changed.length)
|
|
4463
|
+
this.stateRevision++;
|
|
4464
|
+
if (changed.includes("location"))
|
|
4465
|
+
this.checkSubscriptionsAgainstLocation();
|
|
4466
|
+
if (changed.length)
|
|
4467
|
+
this.emitStateChange(changed);
|
|
4468
|
+
} catch (err) {
|
|
4469
|
+
if (revision === this.stateRevision) {
|
|
4470
|
+
console.warn(`[spacemolt] failed to reconcile state after ${action}`, err);
|
|
4471
|
+
}
|
|
4472
|
+
}
|
|
4473
|
+
}
|
|
4352
4474
|
close() {
|
|
4353
4475
|
this.userClosing = true;
|
|
4354
4476
|
this.socket.close();
|
|
@@ -4465,6 +4587,8 @@ class Account {
|
|
|
4465
4587
|
const delta = frame.payload.result;
|
|
4466
4588
|
if (delta) {
|
|
4467
4589
|
const changed = this.cache.applyDelta(delta);
|
|
4590
|
+
if (changed.length)
|
|
4591
|
+
this.stateRevision++;
|
|
4468
4592
|
if (changed.includes("location"))
|
|
4469
4593
|
this.checkSubscriptionsAgainstLocation();
|
|
4470
4594
|
if (changed.length)
|
|
@@ -4499,6 +4623,7 @@ class Account {
|
|
|
4499
4623
|
return;
|
|
4500
4624
|
}
|
|
4501
4625
|
default:
|
|
4626
|
+
this.applyFleetMovementPush(frame);
|
|
4502
4627
|
this.emitter.emit(frame);
|
|
4503
4628
|
}
|
|
4504
4629
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spacemolt/lib",
|
|
3
|
-
"version": "12.2.
|
|
3
|
+
"version": "12.2.1",
|
|
4
4
|
"description": "The definitive TypeScript library for SpaceMolt. WebSocket-v2-first, multi-account, with local state caches. Internals are regenerated from the server's OpenAPI spec.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./dist/index.js",
|