@wumx-labs/noxaeapi-sdk 0.3.5 → 0.4.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/index.d.cts CHANGED
@@ -77,6 +77,11 @@ interface OfflinePlayer {
77
77
  balance: number | null;
78
78
  lastPlayed: number;
79
79
  }
80
+ /** Result of resolving a player name to their UUID via `GET /players/resolve/{name}`. */
81
+ interface PlayerResolveResult {
82
+ name: string;
83
+ uuid: string;
84
+ }
80
85
  interface ServerHealth {
81
86
  cpus: number;
82
87
  uptime: number;
@@ -234,6 +239,61 @@ interface LeaderboardEntry {
234
239
  value: number;
235
240
  [key: string]: unknown;
236
241
  }
242
+ /** Ban details for a player, as reported by `GET /v1/players/{uuid}/profile`'s `status.ban`. */
243
+ interface PlayerProfileBan {
244
+ banned: boolean;
245
+ /** Only present when `banned` is true. */
246
+ reason?: string;
247
+ /** Only present when `banned` is true. */
248
+ source?: string;
249
+ /** Only present when `banned` is true. Serialized server-side as a locale-formatted date string, not ISO-8601. */
250
+ created?: string;
251
+ /** Only present when `banned` is true. `null`/absent means a permanent ban. Same date-string format as `created`. */
252
+ expires?: string | null;
253
+ }
254
+ /** Whitelist + ban status for a player, as reported by `GET /v1/players/{uuid}/profile`'s `status` field. */
255
+ interface PlayerProfileStatus {
256
+ whitelisted: boolean;
257
+ ban: PlayerProfileBan;
258
+ }
259
+ /**
260
+ * Vault economy info for a player, as reported by `GET /v1/players/{uuid}/profile`'s `economy`
261
+ * field. Single-currency (Vault), not ExcellentEconomy's multi-currency system - see
262
+ * `EconomyModule.getCurrencyBalance` for that.
263
+ */
264
+ interface PlayerProfileEconomy {
265
+ available: boolean;
266
+ /** Only present when `available` is true. */
267
+ balance?: number;
268
+ }
269
+ /** One leaderboard source's contribution to a player profile's `stats` array. */
270
+ interface PlayerProfileStatTile {
271
+ id: string;
272
+ label: string;
273
+ status: "ranked" | "not_ranked" | "unavailable";
274
+ /** Only present when `status` is "ranked". */
275
+ value?: number;
276
+ /** Only present when `status` is "ranked" and the source reports a positive rank. */
277
+ rank?: number;
278
+ }
279
+ /**
280
+ * One-call player profile combining identity, whitelist/ban status, Vault balance, and this
281
+ * player's entry in every registered leaderboard source. Returned by
282
+ * `GET /v1/players/{uuid}/profile` and (as the `players` array) by `GET /v1/players/profiles`.
283
+ */
284
+ interface PlayerProfile {
285
+ name: string | null;
286
+ uuid: string;
287
+ online: boolean;
288
+ status: PlayerProfileStatus;
289
+ economy: PlayerProfileEconomy;
290
+ stats: PlayerProfileStatTile[];
291
+ }
292
+ /** Response shape of `GET /v1/players/profiles` (bulk player profiles). */
293
+ interface PlayerProfilesResponse {
294
+ count: number;
295
+ players: PlayerProfile[];
296
+ }
237
297
  interface NetworkServerStatus {
238
298
  id: string;
239
299
  label: string;
@@ -268,6 +328,41 @@ interface NetworkHealthResponse {
268
328
  }
269
329
  /** Per-server "success" | "error" result, keyed by network server ID. */
270
330
  type NetworkBroadcastResponse = Record<string, "success" | "error">;
331
+ /** Last-known state of one backend node, as tracked by the network hub. */
332
+ interface NetworkHubNode {
333
+ id: string;
334
+ label: string;
335
+ online: boolean;
336
+ tps: string;
337
+ onlinePlayers: number;
338
+ maxPlayers: number;
339
+ /** Opaque payload the backend reported in its last heartbeat. Shape isn't fixed by the hub. */
340
+ health: unknown;
341
+ /** Unix epoch ms of the last heartbeat received, or 0 if never. */
342
+ lastHeartbeatAt: number;
343
+ }
344
+ interface NetworkHubStatusResponse {
345
+ network: NetworkHubNode[];
346
+ }
347
+ /** A player as seen directly by the proxy (not reported by a backend). */
348
+ interface NetworkHubPlayer {
349
+ uuid: string;
350
+ name: string;
351
+ /** Backend server ID the player is currently connected to, if known. */
352
+ server?: string;
353
+ }
354
+ interface NetworkHubPlayersResponse {
355
+ total: number;
356
+ players: NetworkHubPlayer[];
357
+ }
358
+ interface NetworkHubFindPlayerResponse {
359
+ found: boolean;
360
+ player?: NetworkHubPlayer;
361
+ }
362
+ /** Result of a proxy-wide broadcast: how many connected players received the message. */
363
+ interface NetworkHubBroadcastResponse {
364
+ delivered: number;
365
+ }
271
366
 
272
367
  declare class PlayersModule {
273
368
  private readonly http;
@@ -278,6 +373,16 @@ declare class PlayersModule {
278
373
  listAll(): Promise<OfflinePlayer[]>;
279
374
  /** Get a single player by UUID (works for online or offline players). */
280
375
  get(uuid: string): Promise<OnlinePlayer | OfflinePlayer>;
376
+ /**
377
+ * Resolve a player name to their UUID using the server's own local player
378
+ * cache (works on both online-mode and offline-mode servers, unlike
379
+ * Mojang's public API - the UUID returned matches whatever this server
380
+ * actually uses for that player's stats/economy/etc). Checks currently
381
+ * online players first, then falls back to the server's offline player
382
+ * cache. Throws `NoxAeApiNotFoundError` if no known player with that name
383
+ * has ever joined.
384
+ */
385
+ resolve(name: string): Promise<PlayerResolveResult>;
281
386
  /** Get a player's inventory in a specific world. */
282
387
  getInventory(playerUuid: string, worldUuid: string): Promise<InventoryItem[]>;
283
388
  /** Kick an online player, optionally with a reason. */
@@ -609,6 +714,10 @@ declare class SkillsModule {
609
714
  * (e.g. the backing plugin isn't loaded) throw `NoxAeApiError` with the
610
715
  * source's own unavailable status (424 for economy currencies, 503 for
611
716
  * mcMMO/AuraSkills) when you call `getTop`.
717
+ *
718
+ * This module also wraps the player-profile routes (`/v1/players/{uuid}/profile`
719
+ * and `/v1/players/profiles`), which live server-side alongside the
720
+ * leaderboard sources since they're built on top of them.
612
721
  */
613
722
  declare class LeaderboardModule {
614
723
  private readonly http;
@@ -617,6 +726,33 @@ declare class LeaderboardModule {
617
726
  list(): Promise<LeaderboardSourceInfo[]>;
618
727
  /** Get ranked entries for one leaderboard source (see `list()` for valid IDs). */
619
728
  getTop(id: string, limit?: number): Promise<LeaderboardEntry[]>;
729
+ /**
730
+ * One-call player profile: identity, whitelist/ban status, Vault balance,
731
+ * and this player's entry in every registered leaderboard source. Built so
732
+ * clients never have to know how many leaderboard sources exist or scan
733
+ * top-N lists themselves.
734
+ *
735
+ * Throws `NoxAeApiNotFoundError` if no known player with that UUID has
736
+ * ever joined.
737
+ */
738
+ getPlayerProfile(uuid: string): Promise<PlayerProfile>;
739
+ /**
740
+ * Bulk player profiles — same shape as `getPlayerProfile`, for many
741
+ * players at once. Computes each leaderboard source's full ranking
742
+ * exactly once for the whole batch rather than once per player, so this
743
+ * is far cheaper than calling `getPlayerProfile` in a loop.
744
+ *
745
+ * Pass `uuids` to fetch an exact, specific set of players — unknown UUIDs
746
+ * are silently skipped rather than throwing. Omit `uuids` to page through
747
+ * every known player instead, using `page`/`limit`, optionally narrowed
748
+ * to only currently-online players via `onlineOnly`.
749
+ */
750
+ getPlayerProfiles(opts?: {
751
+ uuids?: string[];
752
+ page?: number;
753
+ limit?: number;
754
+ onlineOnly?: boolean;
755
+ }): Promise<PlayerProfilesResponse>;
620
756
  }
621
757
 
622
758
  /**
@@ -670,6 +806,69 @@ declare class NetworkModule {
670
806
  }): Promise<T>;
671
807
  }
672
808
 
809
+ /**
810
+ * Wraps the `/v1/network/*` routes exposed by the **NoxAeApi-Velocity**
811
+ * network hub — a separate plugin/process from NoxAeApi-main, run on the
812
+ * Velocity proxy and listening on its own port (`NetworkHubConfig`'s
813
+ * `api-port`, distinct from any individual backend's own REST port).
814
+ *
815
+ * Point a `NoxAeApiNetworkHubClient` (not the regular `NoxAeApiClient`) at
816
+ * that port to use this module. Backend Paper/Bukkit servers connect out
817
+ * to the hub over WebSocket (`/network/register`) and push register /
818
+ * heartbeat / player-join / player-quit events; the hub answers every
819
+ * method below from its own in-memory registry, so calls here are cheap
820
+ * and don't block on a live round trip to each backend the way the older
821
+ * `NetworkModule` (NoxAeApi-main's built-in aggregator) does.
822
+ *
823
+ * Response shapes differ from `NetworkModule` even where the route names
824
+ * match — e.g. `players()` returns one flat proxy-wide player list here,
825
+ * not a per-server breakdown — so the two modules' types aren't
826
+ * interchangeable. There's also no hub equivalent of `/v1/network/health`;
827
+ * each node's last-reported health is embedded in `status*()`'s
828
+ * `NetworkHubNode.health` field instead.
829
+ */
830
+ declare class NetworkHubModule {
831
+ private readonly http;
832
+ constructor(http: HttpEngine);
833
+ /** Get last-known status (from the registry) for every backend node that has ever registered. */
834
+ statusAll(): Promise<NetworkHubStatusResponse>;
835
+ /** Get last-known status for a single node by its configured ID. */
836
+ statusById(id: string): Promise<NetworkHubNode>;
837
+ /**
838
+ * List every player currently connected to the proxy, read straight from
839
+ * Velocity's own player registry (not reported by backends), along with
840
+ * which backend server each is on.
841
+ */
842
+ players(): Promise<NetworkHubPlayersResponse>;
843
+ /** Find which backend server a player is currently on by UUID (proxy-authoritative). */
844
+ findPlayer(uuid: string): Promise<NetworkHubFindPlayerResponse>;
845
+ /**
846
+ * Broadcast a message directly to every player connected to the proxy.
847
+ * Unlike `NetworkModule.broadcast`, this doesn't forward to each
848
+ * backend's `/v1/chat/broadcast` — the proxy already has every player
849
+ * in hand — so it still delivers even to servers with no REST API of
850
+ * their own reachable from the hub.
851
+ */
852
+ broadcast(message: string): Promise<NetworkHubBroadcastResponse>;
853
+ /**
854
+ * Forward an arbitrary request to a specific backend node's own REST
855
+ * API, e.g. `hub.forward("survival", "POST", "server/exec", { body:
856
+ * { command: "say hi" }, form: true })` reaches that backend's
857
+ * `POST /v1/server/exec` directly. Useful for endpoints the hub doesn't
858
+ * have a dedicated method for (economy, worlds, etc) without
859
+ * instantiating a second client pointed at that backend directly.
860
+ *
861
+ * The target backend responds according to its own route's expected
862
+ * encoding (form vs JSON) — pass `form: true` the same way you would for
863
+ * a direct call to that endpoint.
864
+ */
865
+ forward<T = unknown>(id: string, method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH", path: string, opts?: {
866
+ body?: unknown;
867
+ query?: Record<string, QueryValue>;
868
+ form?: boolean;
869
+ }): Promise<T>;
870
+ }
871
+
673
872
  type NoxAeApiWsEvent = "open" | "close" | "error" | "console" | "event" | "message";
674
873
  type Listener = (payload: unknown) => void;
675
874
  interface NoxAeApiWsOptions {
@@ -733,7 +932,17 @@ declare class NoxAeApiClient {
733
932
  readonly skills: SkillsModule;
734
933
  /** Generic ranked leaderboards (economy currencies, mcMMO, AuraSkills, ...). */
735
934
  readonly leaderboards: LeaderboardModule;
736
- /** Only works if `network.enabled: true` is set in the server config. */
935
+ /**
936
+ * Only works if `network.enabled: true` is set in the server config.
937
+ *
938
+ * This is NoxAeApi-main's built-in polling aggregator — it lives on the
939
+ * *same* backend server you're already connected to and fans requests
940
+ * out to the other backends listed in that server's own config. If the
941
+ * network is running NoxAeApi-Velocity instead, use
942
+ * `NoxAeApiNetworkHubClient` (pointed at the proxy's hub port) rather
943
+ * than this module — the hub replaces this aggregator with a push model
944
+ * and its response shapes differ.
945
+ */
737
946
  readonly network: NetworkModule;
738
947
  private readonly http;
739
948
  private readonly baseUrl;
@@ -752,6 +961,33 @@ declare class NoxAeApiClient {
752
961
  /** Open a WebSocket connection to the server (console tail or event stream). */
753
962
  connect(options?: Partial<NoxAeApiWsOptions>): NoxAeApiSocket;
754
963
  }
964
+ /**
965
+ * Client for the **NoxAeApi-Velocity** network hub — a separate plugin
966
+ * that runs on the Velocity proxy, not on any individual backend server.
967
+ * Point `baseUrl` at the hub's own REST port (`NetworkHubConfig`'s
968
+ * `api-port`), not a backend's port, and use `NOXAEAPI_HUB_*` env vars
969
+ * (via `fromEnv`) if you keep that separate from a regular backend's
970
+ * `NOXAEAPI_*` vars.
971
+ *
972
+ * Only exposes `.network` — the hub doesn't run any of the other REST
973
+ * modules (players, economy, worlds, ...) that a backend `NoxAeApiClient`
974
+ * does. To reach a specific backend's own routes through the hub, use
975
+ * `hub.network.forward(id, ...)`.
976
+ */
977
+ declare class NoxAeApiNetworkHubClient {
978
+ /** The network hub's aggregated view of every registered backend node. */
979
+ readonly network: NetworkHubModule;
980
+ constructor(options: NoxAeApiClientOptions);
981
+ /**
982
+ * Build a hub client from environment variables:
983
+ * `NOXAEAPI_HUB_BASE_URL` and `NOXAEAPI_HUB_KEY`.
984
+ *
985
+ * Same convenience as `NoxAeApiClient.fromEnv()`, under separate env var
986
+ * names so a process can hold both a backend client and a hub client at
987
+ * once without the two colliding.
988
+ */
989
+ static fromEnv(overrides?: Partial<NoxAeApiClientOptions>): NoxAeApiNetworkHubClient;
990
+ }
755
991
 
756
992
  interface NoxAeApiErrorInfo {
757
993
  status: number;
@@ -805,4 +1041,4 @@ declare class NoxAeApiNetworkError extends Error {
805
1041
  constructor(message: string, method: string, path: string, cause?: unknown);
806
1042
  }
807
1043
 
808
- export { type Advancement, type CurrencyBalance, type CurrencyTopEntry, type EconomyInfo, type GroupInfo, type InventoryItem, type LeaderboardEntry, type LeaderboardSourceInfo, type NetworkBroadcastResponse, type NetworkFindPlayerResponse, type NetworkHealthResponse, type NetworkHealthServerEntry, type NetworkPlayersResponse, type NetworkPlayersServerEntry, type NetworkServerStatus, NoxAeApiClient, type NoxAeApiClientOptions, NoxAeApiError, NoxAeApiForbiddenError, NoxAeApiNetworkError, NoxAeApiNotFoundError, NoxAeApiRateLimitError, NoxAeApiServerError, NoxAeApiSocket, NoxAeApiUnauthorizedError, type NoxAeApiWsEvent, type NoxAeApiWsOptions, type NoxAuthPlayerInfo, type Objective, type OfflinePlayer, type OnlinePlayer, type PasswordCheckResult, type PermissionNode, type PlayerBalance, type PlayerStats, type Plugin, type RetryOptions, type Score, type Scoreboard, type ServerBan, type ServerHealth, type ServerInfo, type SkillInfo, type TopBalanceEntry, type WhitelistEntry, type World };
1044
+ export { type Advancement, type CurrencyBalance, type CurrencyTopEntry, type EconomyInfo, type GroupInfo, type InventoryItem, type LeaderboardEntry, type LeaderboardSourceInfo, type NetworkBroadcastResponse, type NetworkFindPlayerResponse, type NetworkHealthResponse, type NetworkHealthServerEntry, type NetworkHubBroadcastResponse, type NetworkHubFindPlayerResponse, type NetworkHubNode, type NetworkHubPlayer, type NetworkHubPlayersResponse, type NetworkHubStatusResponse, type NetworkPlayersResponse, type NetworkPlayersServerEntry, type NetworkServerStatus, NoxAeApiClient, type NoxAeApiClientOptions, NoxAeApiError, NoxAeApiForbiddenError, NoxAeApiNetworkError, NoxAeApiNetworkHubClient, NoxAeApiNotFoundError, NoxAeApiRateLimitError, NoxAeApiServerError, NoxAeApiSocket, NoxAeApiUnauthorizedError, type NoxAeApiWsEvent, type NoxAeApiWsOptions, type NoxAuthPlayerInfo, type Objective, type OfflinePlayer, type OnlinePlayer, type PasswordCheckResult, type PermissionNode, type PlayerBalance, type PlayerProfile, type PlayerProfileBan, type PlayerProfileEconomy, type PlayerProfileStatTile, type PlayerProfileStatus, type PlayerProfilesResponse, type PlayerResolveResult, type PlayerStats, type Plugin, type RetryOptions, type Score, type Scoreboard, type ServerBan, type ServerHealth, type ServerInfo, type SkillInfo, type TopBalanceEntry, type WhitelistEntry, type World };
package/dist/index.d.ts CHANGED
@@ -77,6 +77,11 @@ interface OfflinePlayer {
77
77
  balance: number | null;
78
78
  lastPlayed: number;
79
79
  }
80
+ /** Result of resolving a player name to their UUID via `GET /players/resolve/{name}`. */
81
+ interface PlayerResolveResult {
82
+ name: string;
83
+ uuid: string;
84
+ }
80
85
  interface ServerHealth {
81
86
  cpus: number;
82
87
  uptime: number;
@@ -234,6 +239,61 @@ interface LeaderboardEntry {
234
239
  value: number;
235
240
  [key: string]: unknown;
236
241
  }
242
+ /** Ban details for a player, as reported by `GET /v1/players/{uuid}/profile`'s `status.ban`. */
243
+ interface PlayerProfileBan {
244
+ banned: boolean;
245
+ /** Only present when `banned` is true. */
246
+ reason?: string;
247
+ /** Only present when `banned` is true. */
248
+ source?: string;
249
+ /** Only present when `banned` is true. Serialized server-side as a locale-formatted date string, not ISO-8601. */
250
+ created?: string;
251
+ /** Only present when `banned` is true. `null`/absent means a permanent ban. Same date-string format as `created`. */
252
+ expires?: string | null;
253
+ }
254
+ /** Whitelist + ban status for a player, as reported by `GET /v1/players/{uuid}/profile`'s `status` field. */
255
+ interface PlayerProfileStatus {
256
+ whitelisted: boolean;
257
+ ban: PlayerProfileBan;
258
+ }
259
+ /**
260
+ * Vault economy info for a player, as reported by `GET /v1/players/{uuid}/profile`'s `economy`
261
+ * field. Single-currency (Vault), not ExcellentEconomy's multi-currency system - see
262
+ * `EconomyModule.getCurrencyBalance` for that.
263
+ */
264
+ interface PlayerProfileEconomy {
265
+ available: boolean;
266
+ /** Only present when `available` is true. */
267
+ balance?: number;
268
+ }
269
+ /** One leaderboard source's contribution to a player profile's `stats` array. */
270
+ interface PlayerProfileStatTile {
271
+ id: string;
272
+ label: string;
273
+ status: "ranked" | "not_ranked" | "unavailable";
274
+ /** Only present when `status` is "ranked". */
275
+ value?: number;
276
+ /** Only present when `status` is "ranked" and the source reports a positive rank. */
277
+ rank?: number;
278
+ }
279
+ /**
280
+ * One-call player profile combining identity, whitelist/ban status, Vault balance, and this
281
+ * player's entry in every registered leaderboard source. Returned by
282
+ * `GET /v1/players/{uuid}/profile` and (as the `players` array) by `GET /v1/players/profiles`.
283
+ */
284
+ interface PlayerProfile {
285
+ name: string | null;
286
+ uuid: string;
287
+ online: boolean;
288
+ status: PlayerProfileStatus;
289
+ economy: PlayerProfileEconomy;
290
+ stats: PlayerProfileStatTile[];
291
+ }
292
+ /** Response shape of `GET /v1/players/profiles` (bulk player profiles). */
293
+ interface PlayerProfilesResponse {
294
+ count: number;
295
+ players: PlayerProfile[];
296
+ }
237
297
  interface NetworkServerStatus {
238
298
  id: string;
239
299
  label: string;
@@ -268,6 +328,41 @@ interface NetworkHealthResponse {
268
328
  }
269
329
  /** Per-server "success" | "error" result, keyed by network server ID. */
270
330
  type NetworkBroadcastResponse = Record<string, "success" | "error">;
331
+ /** Last-known state of one backend node, as tracked by the network hub. */
332
+ interface NetworkHubNode {
333
+ id: string;
334
+ label: string;
335
+ online: boolean;
336
+ tps: string;
337
+ onlinePlayers: number;
338
+ maxPlayers: number;
339
+ /** Opaque payload the backend reported in its last heartbeat. Shape isn't fixed by the hub. */
340
+ health: unknown;
341
+ /** Unix epoch ms of the last heartbeat received, or 0 if never. */
342
+ lastHeartbeatAt: number;
343
+ }
344
+ interface NetworkHubStatusResponse {
345
+ network: NetworkHubNode[];
346
+ }
347
+ /** A player as seen directly by the proxy (not reported by a backend). */
348
+ interface NetworkHubPlayer {
349
+ uuid: string;
350
+ name: string;
351
+ /** Backend server ID the player is currently connected to, if known. */
352
+ server?: string;
353
+ }
354
+ interface NetworkHubPlayersResponse {
355
+ total: number;
356
+ players: NetworkHubPlayer[];
357
+ }
358
+ interface NetworkHubFindPlayerResponse {
359
+ found: boolean;
360
+ player?: NetworkHubPlayer;
361
+ }
362
+ /** Result of a proxy-wide broadcast: how many connected players received the message. */
363
+ interface NetworkHubBroadcastResponse {
364
+ delivered: number;
365
+ }
271
366
 
272
367
  declare class PlayersModule {
273
368
  private readonly http;
@@ -278,6 +373,16 @@ declare class PlayersModule {
278
373
  listAll(): Promise<OfflinePlayer[]>;
279
374
  /** Get a single player by UUID (works for online or offline players). */
280
375
  get(uuid: string): Promise<OnlinePlayer | OfflinePlayer>;
376
+ /**
377
+ * Resolve a player name to their UUID using the server's own local player
378
+ * cache (works on both online-mode and offline-mode servers, unlike
379
+ * Mojang's public API - the UUID returned matches whatever this server
380
+ * actually uses for that player's stats/economy/etc). Checks currently
381
+ * online players first, then falls back to the server's offline player
382
+ * cache. Throws `NoxAeApiNotFoundError` if no known player with that name
383
+ * has ever joined.
384
+ */
385
+ resolve(name: string): Promise<PlayerResolveResult>;
281
386
  /** Get a player's inventory in a specific world. */
282
387
  getInventory(playerUuid: string, worldUuid: string): Promise<InventoryItem[]>;
283
388
  /** Kick an online player, optionally with a reason. */
@@ -609,6 +714,10 @@ declare class SkillsModule {
609
714
  * (e.g. the backing plugin isn't loaded) throw `NoxAeApiError` with the
610
715
  * source's own unavailable status (424 for economy currencies, 503 for
611
716
  * mcMMO/AuraSkills) when you call `getTop`.
717
+ *
718
+ * This module also wraps the player-profile routes (`/v1/players/{uuid}/profile`
719
+ * and `/v1/players/profiles`), which live server-side alongside the
720
+ * leaderboard sources since they're built on top of them.
612
721
  */
613
722
  declare class LeaderboardModule {
614
723
  private readonly http;
@@ -617,6 +726,33 @@ declare class LeaderboardModule {
617
726
  list(): Promise<LeaderboardSourceInfo[]>;
618
727
  /** Get ranked entries for one leaderboard source (see `list()` for valid IDs). */
619
728
  getTop(id: string, limit?: number): Promise<LeaderboardEntry[]>;
729
+ /**
730
+ * One-call player profile: identity, whitelist/ban status, Vault balance,
731
+ * and this player's entry in every registered leaderboard source. Built so
732
+ * clients never have to know how many leaderboard sources exist or scan
733
+ * top-N lists themselves.
734
+ *
735
+ * Throws `NoxAeApiNotFoundError` if no known player with that UUID has
736
+ * ever joined.
737
+ */
738
+ getPlayerProfile(uuid: string): Promise<PlayerProfile>;
739
+ /**
740
+ * Bulk player profiles — same shape as `getPlayerProfile`, for many
741
+ * players at once. Computes each leaderboard source's full ranking
742
+ * exactly once for the whole batch rather than once per player, so this
743
+ * is far cheaper than calling `getPlayerProfile` in a loop.
744
+ *
745
+ * Pass `uuids` to fetch an exact, specific set of players — unknown UUIDs
746
+ * are silently skipped rather than throwing. Omit `uuids` to page through
747
+ * every known player instead, using `page`/`limit`, optionally narrowed
748
+ * to only currently-online players via `onlineOnly`.
749
+ */
750
+ getPlayerProfiles(opts?: {
751
+ uuids?: string[];
752
+ page?: number;
753
+ limit?: number;
754
+ onlineOnly?: boolean;
755
+ }): Promise<PlayerProfilesResponse>;
620
756
  }
621
757
 
622
758
  /**
@@ -670,6 +806,69 @@ declare class NetworkModule {
670
806
  }): Promise<T>;
671
807
  }
672
808
 
809
+ /**
810
+ * Wraps the `/v1/network/*` routes exposed by the **NoxAeApi-Velocity**
811
+ * network hub — a separate plugin/process from NoxAeApi-main, run on the
812
+ * Velocity proxy and listening on its own port (`NetworkHubConfig`'s
813
+ * `api-port`, distinct from any individual backend's own REST port).
814
+ *
815
+ * Point a `NoxAeApiNetworkHubClient` (not the regular `NoxAeApiClient`) at
816
+ * that port to use this module. Backend Paper/Bukkit servers connect out
817
+ * to the hub over WebSocket (`/network/register`) and push register /
818
+ * heartbeat / player-join / player-quit events; the hub answers every
819
+ * method below from its own in-memory registry, so calls here are cheap
820
+ * and don't block on a live round trip to each backend the way the older
821
+ * `NetworkModule` (NoxAeApi-main's built-in aggregator) does.
822
+ *
823
+ * Response shapes differ from `NetworkModule` even where the route names
824
+ * match — e.g. `players()` returns one flat proxy-wide player list here,
825
+ * not a per-server breakdown — so the two modules' types aren't
826
+ * interchangeable. There's also no hub equivalent of `/v1/network/health`;
827
+ * each node's last-reported health is embedded in `status*()`'s
828
+ * `NetworkHubNode.health` field instead.
829
+ */
830
+ declare class NetworkHubModule {
831
+ private readonly http;
832
+ constructor(http: HttpEngine);
833
+ /** Get last-known status (from the registry) for every backend node that has ever registered. */
834
+ statusAll(): Promise<NetworkHubStatusResponse>;
835
+ /** Get last-known status for a single node by its configured ID. */
836
+ statusById(id: string): Promise<NetworkHubNode>;
837
+ /**
838
+ * List every player currently connected to the proxy, read straight from
839
+ * Velocity's own player registry (not reported by backends), along with
840
+ * which backend server each is on.
841
+ */
842
+ players(): Promise<NetworkHubPlayersResponse>;
843
+ /** Find which backend server a player is currently on by UUID (proxy-authoritative). */
844
+ findPlayer(uuid: string): Promise<NetworkHubFindPlayerResponse>;
845
+ /**
846
+ * Broadcast a message directly to every player connected to the proxy.
847
+ * Unlike `NetworkModule.broadcast`, this doesn't forward to each
848
+ * backend's `/v1/chat/broadcast` — the proxy already has every player
849
+ * in hand — so it still delivers even to servers with no REST API of
850
+ * their own reachable from the hub.
851
+ */
852
+ broadcast(message: string): Promise<NetworkHubBroadcastResponse>;
853
+ /**
854
+ * Forward an arbitrary request to a specific backend node's own REST
855
+ * API, e.g. `hub.forward("survival", "POST", "server/exec", { body:
856
+ * { command: "say hi" }, form: true })` reaches that backend's
857
+ * `POST /v1/server/exec` directly. Useful for endpoints the hub doesn't
858
+ * have a dedicated method for (economy, worlds, etc) without
859
+ * instantiating a second client pointed at that backend directly.
860
+ *
861
+ * The target backend responds according to its own route's expected
862
+ * encoding (form vs JSON) — pass `form: true` the same way you would for
863
+ * a direct call to that endpoint.
864
+ */
865
+ forward<T = unknown>(id: string, method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH", path: string, opts?: {
866
+ body?: unknown;
867
+ query?: Record<string, QueryValue>;
868
+ form?: boolean;
869
+ }): Promise<T>;
870
+ }
871
+
673
872
  type NoxAeApiWsEvent = "open" | "close" | "error" | "console" | "event" | "message";
674
873
  type Listener = (payload: unknown) => void;
675
874
  interface NoxAeApiWsOptions {
@@ -733,7 +932,17 @@ declare class NoxAeApiClient {
733
932
  readonly skills: SkillsModule;
734
933
  /** Generic ranked leaderboards (economy currencies, mcMMO, AuraSkills, ...). */
735
934
  readonly leaderboards: LeaderboardModule;
736
- /** Only works if `network.enabled: true` is set in the server config. */
935
+ /**
936
+ * Only works if `network.enabled: true` is set in the server config.
937
+ *
938
+ * This is NoxAeApi-main's built-in polling aggregator — it lives on the
939
+ * *same* backend server you're already connected to and fans requests
940
+ * out to the other backends listed in that server's own config. If the
941
+ * network is running NoxAeApi-Velocity instead, use
942
+ * `NoxAeApiNetworkHubClient` (pointed at the proxy's hub port) rather
943
+ * than this module — the hub replaces this aggregator with a push model
944
+ * and its response shapes differ.
945
+ */
737
946
  readonly network: NetworkModule;
738
947
  private readonly http;
739
948
  private readonly baseUrl;
@@ -752,6 +961,33 @@ declare class NoxAeApiClient {
752
961
  /** Open a WebSocket connection to the server (console tail or event stream). */
753
962
  connect(options?: Partial<NoxAeApiWsOptions>): NoxAeApiSocket;
754
963
  }
964
+ /**
965
+ * Client for the **NoxAeApi-Velocity** network hub — a separate plugin
966
+ * that runs on the Velocity proxy, not on any individual backend server.
967
+ * Point `baseUrl` at the hub's own REST port (`NetworkHubConfig`'s
968
+ * `api-port`), not a backend's port, and use `NOXAEAPI_HUB_*` env vars
969
+ * (via `fromEnv`) if you keep that separate from a regular backend's
970
+ * `NOXAEAPI_*` vars.
971
+ *
972
+ * Only exposes `.network` — the hub doesn't run any of the other REST
973
+ * modules (players, economy, worlds, ...) that a backend `NoxAeApiClient`
974
+ * does. To reach a specific backend's own routes through the hub, use
975
+ * `hub.network.forward(id, ...)`.
976
+ */
977
+ declare class NoxAeApiNetworkHubClient {
978
+ /** The network hub's aggregated view of every registered backend node. */
979
+ readonly network: NetworkHubModule;
980
+ constructor(options: NoxAeApiClientOptions);
981
+ /**
982
+ * Build a hub client from environment variables:
983
+ * `NOXAEAPI_HUB_BASE_URL` and `NOXAEAPI_HUB_KEY`.
984
+ *
985
+ * Same convenience as `NoxAeApiClient.fromEnv()`, under separate env var
986
+ * names so a process can hold both a backend client and a hub client at
987
+ * once without the two colliding.
988
+ */
989
+ static fromEnv(overrides?: Partial<NoxAeApiClientOptions>): NoxAeApiNetworkHubClient;
990
+ }
755
991
 
756
992
  interface NoxAeApiErrorInfo {
757
993
  status: number;
@@ -805,4 +1041,4 @@ declare class NoxAeApiNetworkError extends Error {
805
1041
  constructor(message: string, method: string, path: string, cause?: unknown);
806
1042
  }
807
1043
 
808
- export { type Advancement, type CurrencyBalance, type CurrencyTopEntry, type EconomyInfo, type GroupInfo, type InventoryItem, type LeaderboardEntry, type LeaderboardSourceInfo, type NetworkBroadcastResponse, type NetworkFindPlayerResponse, type NetworkHealthResponse, type NetworkHealthServerEntry, type NetworkPlayersResponse, type NetworkPlayersServerEntry, type NetworkServerStatus, NoxAeApiClient, type NoxAeApiClientOptions, NoxAeApiError, NoxAeApiForbiddenError, NoxAeApiNetworkError, NoxAeApiNotFoundError, NoxAeApiRateLimitError, NoxAeApiServerError, NoxAeApiSocket, NoxAeApiUnauthorizedError, type NoxAeApiWsEvent, type NoxAeApiWsOptions, type NoxAuthPlayerInfo, type Objective, type OfflinePlayer, type OnlinePlayer, type PasswordCheckResult, type PermissionNode, type PlayerBalance, type PlayerStats, type Plugin, type RetryOptions, type Score, type Scoreboard, type ServerBan, type ServerHealth, type ServerInfo, type SkillInfo, type TopBalanceEntry, type WhitelistEntry, type World };
1044
+ export { type Advancement, type CurrencyBalance, type CurrencyTopEntry, type EconomyInfo, type GroupInfo, type InventoryItem, type LeaderboardEntry, type LeaderboardSourceInfo, type NetworkBroadcastResponse, type NetworkFindPlayerResponse, type NetworkHealthResponse, type NetworkHealthServerEntry, type NetworkHubBroadcastResponse, type NetworkHubFindPlayerResponse, type NetworkHubNode, type NetworkHubPlayer, type NetworkHubPlayersResponse, type NetworkHubStatusResponse, type NetworkPlayersResponse, type NetworkPlayersServerEntry, type NetworkServerStatus, NoxAeApiClient, type NoxAeApiClientOptions, NoxAeApiError, NoxAeApiForbiddenError, NoxAeApiNetworkError, NoxAeApiNetworkHubClient, NoxAeApiNotFoundError, NoxAeApiRateLimitError, NoxAeApiServerError, NoxAeApiSocket, NoxAeApiUnauthorizedError, type NoxAeApiWsEvent, type NoxAeApiWsOptions, type NoxAuthPlayerInfo, type Objective, type OfflinePlayer, type OnlinePlayer, type PasswordCheckResult, type PermissionNode, type PlayerBalance, type PlayerProfile, type PlayerProfileBan, type PlayerProfileEconomy, type PlayerProfileStatTile, type PlayerProfileStatus, type PlayerProfilesResponse, type PlayerResolveResult, type PlayerStats, type Plugin, type RetryOptions, type Score, type Scoreboard, type ServerBan, type ServerHealth, type ServerInfo, type SkillInfo, type TopBalanceEntry, type WhitelistEntry, type World };