@spacemolt/lib 9.0.0 → 10.0.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/dist/data/catalog.d.ts +33 -22
- package/dist/data/stations.d.ts +47 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +29 -15
- package/package.json +1 -1
package/dist/data/catalog.d.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import type { FacilityDefinition, Item, Module, Recipe, ShipClass, SkillDefinition } from '../generated/openapi/types.gen.js';
|
|
1
2
|
/**
|
|
2
3
|
* Local copy of the bulk game catalog (`GET /api/catalog.json`).
|
|
3
4
|
*
|
|
4
5
|
* Reference data — ships, items, recipes, skills, facilities — that changes
|
|
5
|
-
* only on a server release.
|
|
6
|
-
*
|
|
6
|
+
* only on a server release. Entry shapes come from the spec's published
|
|
7
|
+
* `CatalogDump` component types (`ShipClass`, `Item`/`Module`, `Recipe`,
|
|
8
|
+
* `SkillDefinition`, `FacilityDefinition`), so they track the server via the
|
|
9
|
+
* spec sync. Entries are structurally validated as JSON objects and then
|
|
10
|
+
* trusted to match the spec — the same trust model as state-cache deltas.
|
|
7
11
|
*
|
|
8
12
|
* The payload is large (multiple MB), so the server ships it `public,
|
|
9
13
|
* max-age=3600` with a content-hash `ETag`. We keep that ETag on the cache and
|
|
@@ -12,17 +16,20 @@
|
|
|
12
16
|
* catalog after a server release instead of holding the copy it fetched at
|
|
13
17
|
* startup forever (see `SpacemoltClient.catalog`).
|
|
14
18
|
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
/** A ship entry — the spec's `ShipClass` (the dump omits live prices). */
|
|
20
|
+
export type CatalogShip = ShipClass;
|
|
21
|
+
/** An item entry — regular items and modules share the merged `items` list. */
|
|
22
|
+
export type CatalogItem = Item | Module;
|
|
23
|
+
export type CatalogRecipe = Recipe;
|
|
24
|
+
export type CatalogSkill = SkillDefinition;
|
|
25
|
+
export type CatalogFacility = FacilityDefinition;
|
|
19
26
|
export interface Catalog {
|
|
20
27
|
version?: string;
|
|
21
|
-
ships:
|
|
22
|
-
items:
|
|
23
|
-
recipes:
|
|
24
|
-
skills:
|
|
25
|
-
facilities:
|
|
28
|
+
ships: CatalogShip[];
|
|
29
|
+
items: CatalogItem[];
|
|
30
|
+
recipes: CatalogRecipe[];
|
|
31
|
+
skills: CatalogSkill[];
|
|
32
|
+
facilities: CatalogFacility[];
|
|
26
33
|
}
|
|
27
34
|
/** Result of a conditional catalog fetch. */
|
|
28
35
|
export interface CatalogFetchResult {
|
|
@@ -46,7 +53,11 @@ export declare class CatalogCache {
|
|
|
46
53
|
readonly catalog: Catalog;
|
|
47
54
|
/** The server `ETag` this catalog was fetched with, for conditional reloads. */
|
|
48
55
|
readonly etag?: string | undefined;
|
|
49
|
-
private readonly
|
|
56
|
+
private readonly shipsById;
|
|
57
|
+
private readonly itemsById;
|
|
58
|
+
private readonly recipesById;
|
|
59
|
+
private readonly skillsById;
|
|
60
|
+
private readonly facilitiesById;
|
|
50
61
|
constructor(catalog: Catalog,
|
|
51
62
|
/** The server `ETag` this catalog was fetched with, for conditional reloads. */
|
|
52
63
|
etag?: string | undefined);
|
|
@@ -59,14 +70,14 @@ export declare class CatalogCache {
|
|
|
59
70
|
*/
|
|
60
71
|
revalidate(httpBaseUrl: string): Promise<CatalogCache>;
|
|
61
72
|
get version(): string | undefined;
|
|
62
|
-
ship(id: string):
|
|
63
|
-
item(id: string):
|
|
64
|
-
recipe(id: string):
|
|
65
|
-
skill(id: string):
|
|
66
|
-
facility(id: string):
|
|
67
|
-
get ships(): readonly
|
|
68
|
-
get items(): readonly
|
|
69
|
-
get recipes(): readonly
|
|
70
|
-
get skills(): readonly
|
|
71
|
-
get facilities(): readonly
|
|
73
|
+
ship(id: string): CatalogShip | undefined;
|
|
74
|
+
item(id: string): CatalogItem | undefined;
|
|
75
|
+
recipe(id: string): CatalogRecipe | undefined;
|
|
76
|
+
skill(id: string): CatalogSkill | undefined;
|
|
77
|
+
facility(id: string): CatalogFacility | undefined;
|
|
78
|
+
get ships(): readonly CatalogShip[];
|
|
79
|
+
get items(): readonly CatalogItem[];
|
|
80
|
+
get recipes(): readonly CatalogRecipe[];
|
|
81
|
+
get skills(): readonly CatalogSkill[];
|
|
82
|
+
get facilities(): readonly CatalogFacility[];
|
|
72
83
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Station directory (`GET /api/stations`).
|
|
3
|
+
*
|
|
4
|
+
* A public summary of every station in the galaxy — identity, owning
|
|
5
|
+
* empire/faction, system, offered services, condition, and defensive posture —
|
|
6
|
+
* plus the empire display list the server sends alongside it. Live data (the
|
|
7
|
+
* server caches it for ~10s), so fetch on demand rather than caching like the
|
|
8
|
+
* catalog or map.
|
|
9
|
+
*
|
|
10
|
+
* These shapes mirror the server's station list response; they aren't
|
|
11
|
+
* published in the OpenAPI spec yet (see docs/gameserver-todo.md), so they're
|
|
12
|
+
* hand-typed here and kept tolerant of server-side additions via the index
|
|
13
|
+
* signature.
|
|
14
|
+
*/
|
|
15
|
+
export interface StationSummary {
|
|
16
|
+
id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
description: string;
|
|
19
|
+
empire?: string;
|
|
20
|
+
empire_name?: string;
|
|
21
|
+
faction_id?: string;
|
|
22
|
+
faction_name?: string;
|
|
23
|
+
faction_tag?: string;
|
|
24
|
+
faction_color?: string;
|
|
25
|
+
system_id: string;
|
|
26
|
+
system_name: string;
|
|
27
|
+
services: string[];
|
|
28
|
+
condition: string;
|
|
29
|
+
condition_text: string;
|
|
30
|
+
satisfaction_pct: number;
|
|
31
|
+
facility_count: number;
|
|
32
|
+
/** Damage per tick the station's armed guns can actually deliver — zero when its batteries are out of shells. */
|
|
33
|
+
weapon_dps: number;
|
|
34
|
+
wrecked: boolean;
|
|
35
|
+
[key: string]: unknown;
|
|
36
|
+
}
|
|
37
|
+
/** An empire display entry from the station list (`{ id, name }`). */
|
|
38
|
+
export interface StationEmpire {
|
|
39
|
+
id: string;
|
|
40
|
+
name: string;
|
|
41
|
+
}
|
|
42
|
+
export interface StationList {
|
|
43
|
+
stations: StationSummary[];
|
|
44
|
+
empires: StationEmpire[];
|
|
45
|
+
}
|
|
46
|
+
/** Fetch the public station directory. */
|
|
47
|
+
export declare function fetchStations(httpBaseUrl: string): Promise<StationList>;
|
package/dist/index.d.ts
CHANGED
|
@@ -20,8 +20,9 @@ export { MarketCache, type MarketBook, type MarketItem } from './state/market.js
|
|
|
20
20
|
export { ObservationCache, type ObservationView, type ObservedPlayer, type CloakedContact, } from './state/observation.js';
|
|
21
21
|
export { TypedEmitter, EventStream } from './events/emitter.js';
|
|
22
22
|
export { type Commands, type CommandDispatch, buildCommands } from './generated/commands.gen.js';
|
|
23
|
-
export { CatalogCache, fetchCatalog, fetchCatalogConditional, type Catalog, type
|
|
23
|
+
export { CatalogCache, fetchCatalog, fetchCatalogConditional, type Catalog, type CatalogFacility, type CatalogFetchResult, type CatalogItem, type CatalogRecipe, type CatalogShip, type CatalogSkill, } from './data/catalog.js';
|
|
24
24
|
export { MapCache, fetchMap, httpBaseFromWs, type GalaxyMap, type MapSystem } from './data/map.js';
|
|
25
|
+
export { fetchStations, type StationEmpire, type StationList, type StationSummary } from './data/stations.js';
|
|
25
26
|
export { Socket, type SocketOptions, type WebSocketLike, type WebSocketFactory, type MessageEventLike, type CloseEventLike, } from './transport/socket.js';
|
|
26
27
|
export { ACTIONS, GENERATED_SPEC_VERSION } from './generated/actions.gen.js';
|
|
27
28
|
export type { ToolName, ActionName, ActionDef, ActionParam } from './generated/actions.gen.js';
|
package/dist/index.js
CHANGED
|
@@ -4389,7 +4389,7 @@ class MemoryCredentialStore {
|
|
|
4389
4389
|
|
|
4390
4390
|
// src/data/catalog.ts
|
|
4391
4391
|
function catalogEntries(value) {
|
|
4392
|
-
return Array.isArray(value) ? value.filter(
|
|
4392
|
+
return Array.isArray(value) ? value.filter(isRecord) : [];
|
|
4393
4393
|
}
|
|
4394
4394
|
function normalizeCatalog(value) {
|
|
4395
4395
|
const data = requireRecord(value, "catalog response");
|
|
@@ -4429,17 +4429,19 @@ async function fetchCatalog(httpBaseUrl) {
|
|
|
4429
4429
|
class CatalogCache {
|
|
4430
4430
|
catalog;
|
|
4431
4431
|
etag;
|
|
4432
|
-
|
|
4432
|
+
shipsById;
|
|
4433
|
+
itemsById;
|
|
4434
|
+
recipesById;
|
|
4435
|
+
skillsById;
|
|
4436
|
+
facilitiesById;
|
|
4433
4437
|
constructor(catalog, etag) {
|
|
4434
4438
|
this.catalog = catalog;
|
|
4435
4439
|
this.etag = etag;
|
|
4436
|
-
this.
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
facilities: index(catalog.facilities)
|
|
4442
|
-
};
|
|
4440
|
+
this.shipsById = index(catalog.ships);
|
|
4441
|
+
this.itemsById = index(catalog.items);
|
|
4442
|
+
this.recipesById = index(catalog.recipes);
|
|
4443
|
+
this.skillsById = index(catalog.skills);
|
|
4444
|
+
this.facilitiesById = index(catalog.facilities);
|
|
4443
4445
|
}
|
|
4444
4446
|
static async load(httpBaseUrl) {
|
|
4445
4447
|
const { catalog, etag } = await fetchCatalogConditional(httpBaseUrl);
|
|
@@ -4459,19 +4461,19 @@ class CatalogCache {
|
|
|
4459
4461
|
return this.catalog.version;
|
|
4460
4462
|
}
|
|
4461
4463
|
ship(id) {
|
|
4462
|
-
return this.
|
|
4464
|
+
return this.shipsById.get(id);
|
|
4463
4465
|
}
|
|
4464
4466
|
item(id) {
|
|
4465
|
-
return this.
|
|
4467
|
+
return this.itemsById.get(id);
|
|
4466
4468
|
}
|
|
4467
4469
|
recipe(id) {
|
|
4468
|
-
return this.
|
|
4470
|
+
return this.recipesById.get(id);
|
|
4469
4471
|
}
|
|
4470
4472
|
skill(id) {
|
|
4471
|
-
return this.
|
|
4473
|
+
return this.skillsById.get(id);
|
|
4472
4474
|
}
|
|
4473
4475
|
facility(id) {
|
|
4474
|
-
return this.
|
|
4476
|
+
return this.facilitiesById.get(id);
|
|
4475
4477
|
}
|
|
4476
4478
|
get ships() {
|
|
4477
4479
|
return this.catalog.ships;
|
|
@@ -4492,7 +4494,7 @@ class CatalogCache {
|
|
|
4492
4494
|
function index(entries) {
|
|
4493
4495
|
const map = new Map;
|
|
4494
4496
|
for (const entry of entries) {
|
|
4495
|
-
const id = typeof entry.id === "string" ? entry.id : undefined;
|
|
4497
|
+
const id = isRecord(entry) && typeof entry.id === "string" ? entry.id : undefined;
|
|
4496
4498
|
if (id)
|
|
4497
4499
|
map.set(id, entry);
|
|
4498
4500
|
}
|
|
@@ -4840,6 +4842,17 @@ class SpacemoltClient {
|
|
|
4840
4842
|
}
|
|
4841
4843
|
}
|
|
4842
4844
|
}
|
|
4845
|
+
// src/data/stations.ts
|
|
4846
|
+
async function fetchStations(httpBaseUrl) {
|
|
4847
|
+
const url = `${httpBaseUrl.replace(/\/$/, "")}/api/stations`;
|
|
4848
|
+
const res = await fetch(url, { headers: { accept: "application/json" } });
|
|
4849
|
+
if (!res.ok)
|
|
4850
|
+
throw new Error(`GET ${url} -> ${res.status} ${res.statusText}`);
|
|
4851
|
+
const data = requireRecord(await res.json(), "stations response");
|
|
4852
|
+
const stations = Array.isArray(data.stations) ? data.stations.filter(isRecord) : [];
|
|
4853
|
+
const empires = Array.isArray(data.empires) ? data.empires.filter((empire) => isRecord(empire) && typeof empire.id === "string" && typeof empire.name === "string") : [];
|
|
4854
|
+
return { stations, empires };
|
|
4855
|
+
}
|
|
4843
4856
|
// src/generated/notifications.gen.ts
|
|
4844
4857
|
var TYPED_NOTIFICATION_TYPES = [
|
|
4845
4858
|
"achievement_unlocked",
|
|
@@ -4888,6 +4901,7 @@ export {
|
|
|
4888
4901
|
isActionResultFrame,
|
|
4889
4902
|
isActionErrorFrame,
|
|
4890
4903
|
httpBaseFromWs,
|
|
4904
|
+
fetchStations,
|
|
4891
4905
|
fetchMap,
|
|
4892
4906
|
fetchCatalogConditional,
|
|
4893
4907
|
fetchCatalog,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spacemolt/lib",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.0",
|
|
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",
|