@wumx-labs/noxaeapi-sdk 0.2.0 → 0.3.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/index.d.cts CHANGED
@@ -207,6 +207,67 @@ interface SkillInfo {
207
207
  skills: Record<string, number>;
208
208
  powerLevel: number;
209
209
  }
210
+ /** A single currency configured on ExcellentEconomy (multi-currency, non-Vault). */
211
+ interface CurrencyBalance {
212
+ uuid: string;
213
+ name: string | null;
214
+ currency: string;
215
+ balance: number;
216
+ }
217
+ interface CurrencyTopEntry {
218
+ uuid: string;
219
+ name: string;
220
+ balance: number;
221
+ }
222
+ /** Entry returned by `GET /v1/leaderboards` describing one registered leaderboard source. */
223
+ interface LeaderboardSourceInfo {
224
+ id: string;
225
+ displayName: string;
226
+ available: boolean;
227
+ /** True if this source can only rank currently-online players (e.g. mcMMO). */
228
+ onlineOnly: boolean;
229
+ }
230
+ /** A single ranked entry from `GET /v1/leaderboards/{id}/top`. Shape can vary slightly by source. */
231
+ interface LeaderboardEntry {
232
+ uuid: string;
233
+ name: string;
234
+ value: number;
235
+ [key: string]: unknown;
236
+ }
237
+ interface NetworkServerStatus {
238
+ id: string;
239
+ label: string;
240
+ online: boolean;
241
+ server: ServerInfo | null;
242
+ players: OnlinePlayer[];
243
+ }
244
+ interface NetworkPlayersServerEntry {
245
+ id: string;
246
+ label: string;
247
+ online: boolean;
248
+ players: OnlinePlayer[];
249
+ }
250
+ interface NetworkPlayersResponse {
251
+ total: number;
252
+ servers: NetworkPlayersServerEntry[];
253
+ }
254
+ interface NetworkFindPlayerResponse {
255
+ found: boolean;
256
+ server?: string;
257
+ player?: OnlinePlayer;
258
+ }
259
+ interface NetworkHealthServerEntry {
260
+ id: string;
261
+ label: string;
262
+ online: boolean;
263
+ tps?: unknown;
264
+ health?: unknown;
265
+ }
266
+ interface NetworkHealthResponse {
267
+ servers: NetworkHealthServerEntry[];
268
+ }
269
+ /** Per-server "success" | "error" result, keyed by network server ID. */
270
+ type NetworkBroadcastResponse = Record<string, "success" | "error">;
210
271
 
211
272
  declare class PlayersModule {
212
273
  private readonly http;
@@ -254,6 +315,27 @@ declare class EconomyModule {
254
315
  pay(uuid: string, amount: number): Promise<void>;
255
316
  /** Debit an amount from a player (subtracts from their balance). */
256
317
  debit(uuid: string, amount: number): Promise<void>;
318
+ /** List all currency IDs configured on ExcellentEconomy. */
319
+ listCurrencies(): Promise<string[]>;
320
+ /** Get a player's balance for a specific ExcellentEconomy currency. */
321
+ getCurrencyBalance(currency: string, uuid: string): Promise<CurrencyBalance>;
322
+ /**
323
+ * Pay a player in a specific currency (adds `amount` to their balance).
324
+ * `amount` must be greater than zero.
325
+ */
326
+ payCurrency(currency: string, uuid: string, amount: number): Promise<"success" | "failure">;
327
+ /**
328
+ * Debit a player in a specific currency (subtracts `amount` from their
329
+ * balance). `amount` must be greater than zero.
330
+ */
331
+ debitCurrency(currency: string, uuid: string, amount: number): Promise<"success" | "failure">;
332
+ /**
333
+ * Set a player's balance for a specific currency to an exact amount
334
+ * (`amount` must be >= 0), rather than adding/subtracting.
335
+ */
336
+ setCurrencyBalance(currency: string, uuid: string, amount: number): Promise<"success" | "failure">;
337
+ /** Get the top balances leaderboard for a specific currency. */
338
+ getCurrencyTop(currency: string, limit?: number): Promise<CurrencyTopEntry[]>;
257
339
  }
258
340
 
259
341
  declare class ServerModule {
@@ -458,6 +540,20 @@ declare class LuckPermsModule {
458
540
  removePlayerGroup(uuid: string, groupName: string): Promise<void>;
459
541
  /** List all known groups. */
460
542
  getGroups(): Promise<string[]>;
543
+ /**
544
+ * Create a new LuckPerms group. The name is lowercased server-side.
545
+ * Throws `NoxAeApiError` with a 409 status if the group already exists.
546
+ */
547
+ createGroup(name: string): Promise<{
548
+ name: string;
549
+ status: string;
550
+ }>;
551
+ /**
552
+ * Delete a LuckPerms group by name.
553
+ * The `default` group can't be deleted (400 — every user without an
554
+ * explicit group inherits from it) and a 404 is thrown if it doesn't exist.
555
+ */
556
+ deleteGroup(name: string): Promise<void>;
461
557
  /** Get the permissions attached to a specific group. */
462
558
  getGroupPermissions(name: string): Promise<GroupInfo>;
463
559
  }
@@ -502,6 +598,78 @@ declare class SkillsModule {
502
598
  getAuraSkills(uuid: string): Promise<SkillInfo>;
503
599
  }
504
600
 
601
+ /**
602
+ * Wraps the generic, pluggable `/v1/leaderboards/*` routes. This is a
603
+ * unified view over every ranking source registered on the server —
604
+ * economy currencies, mcMMO power level, AuraSkills power level, etc —
605
+ * so you don't need to know ahead of time which plugins are installed.
606
+ *
607
+ * Use `list()` to discover available source IDs, then pass one to
608
+ * `getTop(id)`. Sources that are registered but currently unavailable
609
+ * (e.g. the backing plugin isn't loaded) throw `NoxAeApiError` with the
610
+ * source's own unavailable status (424 for economy currencies, 503 for
611
+ * mcMMO/AuraSkills) when you call `getTop`.
612
+ */
613
+ declare class LeaderboardModule {
614
+ private readonly http;
615
+ constructor(http: HttpEngine);
616
+ /** List every registered leaderboard source and its availability. */
617
+ list(): Promise<LeaderboardSourceInfo[]>;
618
+ /** Get ranked entries for one leaderboard source (see `list()` for valid IDs). */
619
+ getTop(id: string, limit?: number): Promise<LeaderboardEntry[]>;
620
+ }
621
+
622
+ /**
623
+ * Wraps the `/v1/network/*` routes. These only exist when `network.enabled:
624
+ * true` is set in the server's config with at least one backend server
625
+ * configured — calling any method here against a server without the
626
+ * network aggregator enabled will 404.
627
+ *
628
+ * The aggregator fans requests out to every configured backend server
629
+ * (each with its own base URL + key) and merges the results, so a single
630
+ * call here can reflect the state of an entire network rather than just
631
+ * the server you connected to.
632
+ */
633
+ declare class NetworkModule {
634
+ private readonly http;
635
+ constructor(http: HttpEngine);
636
+ /** Get status (server info + online players) for every configured network server. */
637
+ statusAll(): Promise<{
638
+ network: NetworkServerStatus[];
639
+ }>;
640
+ /** Get status for a single network server by its configured ID. */
641
+ statusById(id: string): Promise<NetworkServerStatus>;
642
+ /** Aggregate online players across every network server. */
643
+ players(): Promise<NetworkPlayersResponse>;
644
+ /** Find which network server a player is currently on by UUID. */
645
+ findPlayer(uuid: string): Promise<NetworkFindPlayerResponse>;
646
+ /** Get aggregate health (TPS/memory) from every network server. */
647
+ health(): Promise<NetworkHealthResponse>;
648
+ /**
649
+ * Broadcast a message to every server on the network.
650
+ * Returns a map of server ID -> "success" | "error" (per-server delivery
651
+ * result; a network-wide failure is only thrown for a malformed request).
652
+ */
653
+ broadcast(message: string): Promise<Record<string, "success" | "error">>;
654
+ /**
655
+ * Forward an arbitrary request to a specific network server's own REST
656
+ * API, e.g. `network.forward("survival", "POST", "server/exec", { body:
657
+ * { command: "say hi" }, form: true })` reaches that server's
658
+ * `POST /v1/server/exec` directly. Useful for endpoints the aggregator
659
+ * doesn't have a dedicated method for (economy, worlds, etc) on a
660
+ * specific server without instantiating a second client pointed at it.
661
+ *
662
+ * Note the target server responds according to its own route's expected
663
+ * encoding (form vs JSON) — pass `form: true` the same way you would for
664
+ * a direct call to that endpoint.
665
+ */
666
+ forward<T = unknown>(id: string, method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH", path: string, opts?: {
667
+ body?: unknown;
668
+ query?: Record<string, QueryValue>;
669
+ form?: boolean;
670
+ }): Promise<T>;
671
+ }
672
+
505
673
  type NoxAeApiWsEvent = "open" | "close" | "error" | "console" | "event" | "message";
506
674
  type Listener = (payload: unknown) => void;
507
675
  interface NoxAeApiWsOptions {
@@ -563,6 +731,10 @@ declare class NoxAeApiClient {
563
731
  readonly noxauth: NoxAuthModule;
564
732
  /** Requires mcMMO and/or AuraSkills to be loaded on the target server. */
565
733
  readonly skills: SkillsModule;
734
+ /** Generic ranked leaderboards (economy currencies, mcMMO, AuraSkills, ...). */
735
+ readonly leaderboards: LeaderboardModule;
736
+ /** Only works if `network.enabled: true` is set in the server config. */
737
+ readonly network: NetworkModule;
566
738
  private readonly http;
567
739
  private readonly baseUrl;
568
740
  private readonly apiKey?;
@@ -633,4 +805,4 @@ declare class NoxAeApiNetworkError extends Error {
633
805
  constructor(message: string, method: string, path: string, cause?: unknown);
634
806
  }
635
807
 
636
- export { type Advancement, type EconomyInfo, type GroupInfo, type InventoryItem, 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 };
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 };
package/dist/index.d.ts CHANGED
@@ -207,6 +207,67 @@ interface SkillInfo {
207
207
  skills: Record<string, number>;
208
208
  powerLevel: number;
209
209
  }
210
+ /** A single currency configured on ExcellentEconomy (multi-currency, non-Vault). */
211
+ interface CurrencyBalance {
212
+ uuid: string;
213
+ name: string | null;
214
+ currency: string;
215
+ balance: number;
216
+ }
217
+ interface CurrencyTopEntry {
218
+ uuid: string;
219
+ name: string;
220
+ balance: number;
221
+ }
222
+ /** Entry returned by `GET /v1/leaderboards` describing one registered leaderboard source. */
223
+ interface LeaderboardSourceInfo {
224
+ id: string;
225
+ displayName: string;
226
+ available: boolean;
227
+ /** True if this source can only rank currently-online players (e.g. mcMMO). */
228
+ onlineOnly: boolean;
229
+ }
230
+ /** A single ranked entry from `GET /v1/leaderboards/{id}/top`. Shape can vary slightly by source. */
231
+ interface LeaderboardEntry {
232
+ uuid: string;
233
+ name: string;
234
+ value: number;
235
+ [key: string]: unknown;
236
+ }
237
+ interface NetworkServerStatus {
238
+ id: string;
239
+ label: string;
240
+ online: boolean;
241
+ server: ServerInfo | null;
242
+ players: OnlinePlayer[];
243
+ }
244
+ interface NetworkPlayersServerEntry {
245
+ id: string;
246
+ label: string;
247
+ online: boolean;
248
+ players: OnlinePlayer[];
249
+ }
250
+ interface NetworkPlayersResponse {
251
+ total: number;
252
+ servers: NetworkPlayersServerEntry[];
253
+ }
254
+ interface NetworkFindPlayerResponse {
255
+ found: boolean;
256
+ server?: string;
257
+ player?: OnlinePlayer;
258
+ }
259
+ interface NetworkHealthServerEntry {
260
+ id: string;
261
+ label: string;
262
+ online: boolean;
263
+ tps?: unknown;
264
+ health?: unknown;
265
+ }
266
+ interface NetworkHealthResponse {
267
+ servers: NetworkHealthServerEntry[];
268
+ }
269
+ /** Per-server "success" | "error" result, keyed by network server ID. */
270
+ type NetworkBroadcastResponse = Record<string, "success" | "error">;
210
271
 
211
272
  declare class PlayersModule {
212
273
  private readonly http;
@@ -254,6 +315,27 @@ declare class EconomyModule {
254
315
  pay(uuid: string, amount: number): Promise<void>;
255
316
  /** Debit an amount from a player (subtracts from their balance). */
256
317
  debit(uuid: string, amount: number): Promise<void>;
318
+ /** List all currency IDs configured on ExcellentEconomy. */
319
+ listCurrencies(): Promise<string[]>;
320
+ /** Get a player's balance for a specific ExcellentEconomy currency. */
321
+ getCurrencyBalance(currency: string, uuid: string): Promise<CurrencyBalance>;
322
+ /**
323
+ * Pay a player in a specific currency (adds `amount` to their balance).
324
+ * `amount` must be greater than zero.
325
+ */
326
+ payCurrency(currency: string, uuid: string, amount: number): Promise<"success" | "failure">;
327
+ /**
328
+ * Debit a player in a specific currency (subtracts `amount` from their
329
+ * balance). `amount` must be greater than zero.
330
+ */
331
+ debitCurrency(currency: string, uuid: string, amount: number): Promise<"success" | "failure">;
332
+ /**
333
+ * Set a player's balance for a specific currency to an exact amount
334
+ * (`amount` must be >= 0), rather than adding/subtracting.
335
+ */
336
+ setCurrencyBalance(currency: string, uuid: string, amount: number): Promise<"success" | "failure">;
337
+ /** Get the top balances leaderboard for a specific currency. */
338
+ getCurrencyTop(currency: string, limit?: number): Promise<CurrencyTopEntry[]>;
257
339
  }
258
340
 
259
341
  declare class ServerModule {
@@ -458,6 +540,20 @@ declare class LuckPermsModule {
458
540
  removePlayerGroup(uuid: string, groupName: string): Promise<void>;
459
541
  /** List all known groups. */
460
542
  getGroups(): Promise<string[]>;
543
+ /**
544
+ * Create a new LuckPerms group. The name is lowercased server-side.
545
+ * Throws `NoxAeApiError` with a 409 status if the group already exists.
546
+ */
547
+ createGroup(name: string): Promise<{
548
+ name: string;
549
+ status: string;
550
+ }>;
551
+ /**
552
+ * Delete a LuckPerms group by name.
553
+ * The `default` group can't be deleted (400 — every user without an
554
+ * explicit group inherits from it) and a 404 is thrown if it doesn't exist.
555
+ */
556
+ deleteGroup(name: string): Promise<void>;
461
557
  /** Get the permissions attached to a specific group. */
462
558
  getGroupPermissions(name: string): Promise<GroupInfo>;
463
559
  }
@@ -502,6 +598,78 @@ declare class SkillsModule {
502
598
  getAuraSkills(uuid: string): Promise<SkillInfo>;
503
599
  }
504
600
 
601
+ /**
602
+ * Wraps the generic, pluggable `/v1/leaderboards/*` routes. This is a
603
+ * unified view over every ranking source registered on the server —
604
+ * economy currencies, mcMMO power level, AuraSkills power level, etc —
605
+ * so you don't need to know ahead of time which plugins are installed.
606
+ *
607
+ * Use `list()` to discover available source IDs, then pass one to
608
+ * `getTop(id)`. Sources that are registered but currently unavailable
609
+ * (e.g. the backing plugin isn't loaded) throw `NoxAeApiError` with the
610
+ * source's own unavailable status (424 for economy currencies, 503 for
611
+ * mcMMO/AuraSkills) when you call `getTop`.
612
+ */
613
+ declare class LeaderboardModule {
614
+ private readonly http;
615
+ constructor(http: HttpEngine);
616
+ /** List every registered leaderboard source and its availability. */
617
+ list(): Promise<LeaderboardSourceInfo[]>;
618
+ /** Get ranked entries for one leaderboard source (see `list()` for valid IDs). */
619
+ getTop(id: string, limit?: number): Promise<LeaderboardEntry[]>;
620
+ }
621
+
622
+ /**
623
+ * Wraps the `/v1/network/*` routes. These only exist when `network.enabled:
624
+ * true` is set in the server's config with at least one backend server
625
+ * configured — calling any method here against a server without the
626
+ * network aggregator enabled will 404.
627
+ *
628
+ * The aggregator fans requests out to every configured backend server
629
+ * (each with its own base URL + key) and merges the results, so a single
630
+ * call here can reflect the state of an entire network rather than just
631
+ * the server you connected to.
632
+ */
633
+ declare class NetworkModule {
634
+ private readonly http;
635
+ constructor(http: HttpEngine);
636
+ /** Get status (server info + online players) for every configured network server. */
637
+ statusAll(): Promise<{
638
+ network: NetworkServerStatus[];
639
+ }>;
640
+ /** Get status for a single network server by its configured ID. */
641
+ statusById(id: string): Promise<NetworkServerStatus>;
642
+ /** Aggregate online players across every network server. */
643
+ players(): Promise<NetworkPlayersResponse>;
644
+ /** Find which network server a player is currently on by UUID. */
645
+ findPlayer(uuid: string): Promise<NetworkFindPlayerResponse>;
646
+ /** Get aggregate health (TPS/memory) from every network server. */
647
+ health(): Promise<NetworkHealthResponse>;
648
+ /**
649
+ * Broadcast a message to every server on the network.
650
+ * Returns a map of server ID -> "success" | "error" (per-server delivery
651
+ * result; a network-wide failure is only thrown for a malformed request).
652
+ */
653
+ broadcast(message: string): Promise<Record<string, "success" | "error">>;
654
+ /**
655
+ * Forward an arbitrary request to a specific network server's own REST
656
+ * API, e.g. `network.forward("survival", "POST", "server/exec", { body:
657
+ * { command: "say hi" }, form: true })` reaches that server's
658
+ * `POST /v1/server/exec` directly. Useful for endpoints the aggregator
659
+ * doesn't have a dedicated method for (economy, worlds, etc) on a
660
+ * specific server without instantiating a second client pointed at it.
661
+ *
662
+ * Note the target server responds according to its own route's expected
663
+ * encoding (form vs JSON) — pass `form: true` the same way you would for
664
+ * a direct call to that endpoint.
665
+ */
666
+ forward<T = unknown>(id: string, method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH", path: string, opts?: {
667
+ body?: unknown;
668
+ query?: Record<string, QueryValue>;
669
+ form?: boolean;
670
+ }): Promise<T>;
671
+ }
672
+
505
673
  type NoxAeApiWsEvent = "open" | "close" | "error" | "console" | "event" | "message";
506
674
  type Listener = (payload: unknown) => void;
507
675
  interface NoxAeApiWsOptions {
@@ -563,6 +731,10 @@ declare class NoxAeApiClient {
563
731
  readonly noxauth: NoxAuthModule;
564
732
  /** Requires mcMMO and/or AuraSkills to be loaded on the target server. */
565
733
  readonly skills: SkillsModule;
734
+ /** Generic ranked leaderboards (economy currencies, mcMMO, AuraSkills, ...). */
735
+ readonly leaderboards: LeaderboardModule;
736
+ /** Only works if `network.enabled: true` is set in the server config. */
737
+ readonly network: NetworkModule;
566
738
  private readonly http;
567
739
  private readonly baseUrl;
568
740
  private readonly apiKey?;
@@ -633,4 +805,4 @@ declare class NoxAeApiNetworkError extends Error {
633
805
  constructor(message: string, method: string, path: string, cause?: unknown);
634
806
  }
635
807
 
636
- export { type Advancement, type EconomyInfo, type GroupInfo, type InventoryItem, 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 };
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 };
package/dist/index.js CHANGED
@@ -324,6 +324,61 @@ var EconomyModule = class {
324
324
  debit(uuid, amount) {
325
325
  return this.http.request("POST", "economy/debit", { body: { uuid, amount }, form: true });
326
326
  }
327
+ // ─── ExcellentEconomy multi-currency (native API, not Vault) ────────────
328
+ //
329
+ // These endpoints talk directly to ExcellentEconomy's Developer API rather
330
+ // than Vault, so they work with any currency configured on the server
331
+ // (coins, gems, tokens, ...) instead of only the single Vault-linked
332
+ // "primary" currency exposed above. They throw `NoxAeApiError` with a 424
333
+ // status if ExcellentEconomy isn't installed on the target server, and a
334
+ // 404 if the given currency ID doesn't exist.
335
+ /** List all currency IDs configured on ExcellentEconomy. */
336
+ listCurrencies() {
337
+ return this.http.request("GET", "economy/currencies");
338
+ }
339
+ /** Get a player's balance for a specific ExcellentEconomy currency. */
340
+ getCurrencyBalance(currency, uuid) {
341
+ return this.http.request(
342
+ "GET",
343
+ `economy/currency/${encodeURIComponent(currency)}/balance/${encodeURIComponent(uuid)}`
344
+ );
345
+ }
346
+ /**
347
+ * Pay a player in a specific currency (adds `amount` to their balance).
348
+ * `amount` must be greater than zero.
349
+ */
350
+ payCurrency(currency, uuid, amount) {
351
+ return this.http.request("POST", `economy/currency/${encodeURIComponent(currency)}/pay`, {
352
+ body: { uuid, amount },
353
+ form: true
354
+ });
355
+ }
356
+ /**
357
+ * Debit a player in a specific currency (subtracts `amount` from their
358
+ * balance). `amount` must be greater than zero.
359
+ */
360
+ debitCurrency(currency, uuid, amount) {
361
+ return this.http.request("POST", `economy/currency/${encodeURIComponent(currency)}/debit`, {
362
+ body: { uuid, amount },
363
+ form: true
364
+ });
365
+ }
366
+ /**
367
+ * Set a player's balance for a specific currency to an exact amount
368
+ * (`amount` must be >= 0), rather than adding/subtracting.
369
+ */
370
+ setCurrencyBalance(currency, uuid, amount) {
371
+ return this.http.request("POST", `economy/currency/${encodeURIComponent(currency)}/set`, {
372
+ body: { uuid, amount },
373
+ form: true
374
+ });
375
+ }
376
+ /** Get the top balances leaderboard for a specific currency. */
377
+ getCurrencyTop(currency, limit) {
378
+ return this.http.request("GET", `economy/currency/${encodeURIComponent(currency)}/top`, {
379
+ query: { limit }
380
+ });
381
+ }
327
382
  };
328
383
 
329
384
  // src/modules/server.ts
@@ -637,6 +692,21 @@ var LuckPermsModule = class {
637
692
  getGroups() {
638
693
  return this.http.request("GET", "luckperms/groups");
639
694
  }
695
+ /**
696
+ * Create a new LuckPerms group. The name is lowercased server-side.
697
+ * Throws `NoxAeApiError` with a 409 status if the group already exists.
698
+ */
699
+ createGroup(name) {
700
+ return this.http.request("POST", "luckperms/groups", { body: { name } });
701
+ }
702
+ /**
703
+ * Delete a LuckPerms group by name.
704
+ * The `default` group can't be deleted (400 — every user without an
705
+ * explicit group inherits from it) and a 404 is thrown if it doesn't exist.
706
+ */
707
+ deleteGroup(name) {
708
+ return this.http.request("DELETE", `luckperms/group/${encodeURIComponent(name)}`);
709
+ }
640
710
  /** Get the permissions attached to a specific group. */
641
711
  getGroupPermissions(name) {
642
712
  return this.http.request("GET", `luckperms/group/${encodeURIComponent(name)}/permissions`);
@@ -689,6 +759,75 @@ var SkillsModule = class {
689
759
  }
690
760
  };
691
761
 
762
+ // src/modules/leaderboard.ts
763
+ var LeaderboardModule = class {
764
+ constructor(http) {
765
+ this.http = http;
766
+ }
767
+ http;
768
+ /** List every registered leaderboard source and its availability. */
769
+ list() {
770
+ return this.http.request("GET", "leaderboards");
771
+ }
772
+ /** Get ranked entries for one leaderboard source (see `list()` for valid IDs). */
773
+ getTop(id, limit) {
774
+ return this.http.request("GET", `leaderboards/${encodeURIComponent(id)}/top`, {
775
+ query: { limit }
776
+ });
777
+ }
778
+ };
779
+
780
+ // src/modules/network.ts
781
+ var NetworkModule = class {
782
+ constructor(http) {
783
+ this.http = http;
784
+ }
785
+ http;
786
+ /** Get status (server info + online players) for every configured network server. */
787
+ statusAll() {
788
+ return this.http.request("GET", "network/status");
789
+ }
790
+ /** Get status for a single network server by its configured ID. */
791
+ statusById(id) {
792
+ return this.http.request("GET", `network/status/${encodeURIComponent(id)}`);
793
+ }
794
+ /** Aggregate online players across every network server. */
795
+ players() {
796
+ return this.http.request("GET", "network/players");
797
+ }
798
+ /** Find which network server a player is currently on by UUID. */
799
+ findPlayer(uuid) {
800
+ return this.http.request("GET", `network/players/${encodeURIComponent(uuid)}`);
801
+ }
802
+ /** Get aggregate health (TPS/memory) from every network server. */
803
+ health() {
804
+ return this.http.request("GET", "network/health");
805
+ }
806
+ /**
807
+ * Broadcast a message to every server on the network.
808
+ * Returns a map of server ID -> "success" | "error" (per-server delivery
809
+ * result; a network-wide failure is only thrown for a malformed request).
810
+ */
811
+ broadcast(message) {
812
+ return this.http.request("POST", "network/broadcast", { body: { message }, form: true });
813
+ }
814
+ /**
815
+ * Forward an arbitrary request to a specific network server's own REST
816
+ * API, e.g. `network.forward("survival", "POST", "server/exec", { body:
817
+ * { command: "say hi" }, form: true })` reaches that server's
818
+ * `POST /v1/server/exec` directly. Useful for endpoints the aggregator
819
+ * doesn't have a dedicated method for (economy, worlds, etc) on a
820
+ * specific server without instantiating a second client pointed at it.
821
+ *
822
+ * Note the target server responds according to its own route's expected
823
+ * encoding (form vs JSON) — pass `form: true` the same way you would for
824
+ * a direct call to that endpoint.
825
+ */
826
+ forward(id, method, path, opts = {}) {
827
+ return this.http.request(method, `network/${encodeURIComponent(id)}/${path.replace(/^\/+/, "")}`, opts);
828
+ }
829
+ };
830
+
692
831
  // src/socket.ts
693
832
  function toWsUrl(baseUrl, route, apiKey) {
694
833
  const url = new URL(`${baseUrl.replace(/\/+$/, "")}/v1/ws/${route.replace(/^\/+/, "")}`);
@@ -796,6 +935,10 @@ var NoxAeApiClient = class _NoxAeApiClient {
796
935
  noxauth;
797
936
  /** Requires mcMMO and/or AuraSkills to be loaded on the target server. */
798
937
  skills;
938
+ /** Generic ranked leaderboards (economy currencies, mcMMO, AuraSkills, ...). */
939
+ leaderboards;
940
+ /** Only works if `network.enabled: true` is set in the server config. */
941
+ network;
799
942
  http;
800
943
  baseUrl;
801
944
  apiKey;
@@ -813,6 +956,8 @@ var NoxAeApiClient = class _NoxAeApiClient {
813
956
  this.luckperms = new LuckPermsModule(this.http);
814
957
  this.noxauth = new NoxAuthModule(this.http);
815
958
  this.skills = new SkillsModule(this.http);
959
+ this.leaderboards = new LeaderboardModule(this.http);
960
+ this.network = new NetworkModule(this.http);
816
961
  }
817
962
  /**
818
963
  * Build a client from environment variables: