clashofclans.js 3.1.2 → 3.1.3-dev.048e4b9

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
@@ -12,7 +12,7 @@
12
12
  ### Installation
13
13
 
14
14
  - **`npm i clashofclans.js`**
15
- - **Node.js v14 or newer is required.**
15
+ - **Node.js v16 or newer is required.**
16
16
 
17
17
  ### Links
18
18
 
@@ -1,10 +1,10 @@
1
1
  /// <reference types="node" />
2
2
  import { EventEmitter } from 'node:events';
3
- import { ClanSearchOptions, SearchOptions, ClientOptions, LoginOptions, OverrideOptions } from '../types';
4
- import { CWLRounds, ClientEvents } from '../util/Constants';
5
3
  import { RESTManager } from '../rest/RESTManager';
4
+ import { ClanSearchOptions, ClientOptions, LoginOptions, OverrideOptions, SearchOptions } from '../types';
5
+ import { CWLRounds, ClientEvents } from '../util/Constants';
6
6
  import { Util } from '../util/Util';
7
- import { Clan, ClanMember, ClanWar, ClanWarLog, Location, Player, RankedClan, RankedPlayer, SeasonRankedPlayer, GoldPassSeason, ClanWarLeagueGroup } from '../struct';
7
+ import { Clan, ClanMember, ClanWar, ClanWarLeagueGroup, ClanWarLog, GoldPassSeason, Location, Player, RankedClan, RankedPlayer, SeasonRankedPlayer } from '../struct';
8
8
  import { CapitalRaidSeason } from '../struct/CapitalRaidSeason';
9
9
  interface IClientEvents {
10
10
  [ClientEvents.Error]: [error: unknown];
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Client = void 0;
4
4
  const node_events_1 = require("node:events");
5
- const Constants_1 = require("../util/Constants");
6
5
  const HTTPError_1 = require("../rest/HTTPError");
7
6
  const RESTManager_1 = require("../rest/RESTManager");
7
+ const Constants_1 = require("../util/Constants");
8
8
  const Util_1 = require("../util/Util");
9
9
  const struct_1 = require("../struct");
10
10
  const CapitalRaidSeason_1 = require("../struct/CapitalRaidSeason");
@@ -75,8 +75,8 @@ class Client extends node_events_1.EventEmitter {
75
75
  }
76
76
  /** Get info about currently running war (normal or friendly) in the clan. */
77
77
  async getClanWar(clanTag, options) {
78
- const { data, maxAge } = await this.rest.getCurrentWar(clanTag, options);
79
- return new struct_1.ClanWar(this, data, { clanTag, maxAge });
78
+ const { data, res } = await this.rest.getCurrentWar(clanTag, options);
79
+ return new struct_1.ClanWar(this, data, { clanTag, maxAge: res.maxAge });
80
80
  }
81
81
  /**
82
82
  * Get info about currently running war in the clan.
@@ -166,8 +166,8 @@ class Client extends node_events_1.EventEmitter {
166
166
  /** Get info about a CWL round by WarTag. */
167
167
  async getClanWarLeagueRound(warTag, options) {
168
168
  const args = typeof warTag === 'string' ? { warTag } : { warTag: warTag.warTag, clanTag: warTag.clanTag };
169
- const { data, maxAge } = await this.rest.getClanWarLeagueRound(args.warTag, options);
170
- return new struct_1.ClanWar(this, data, { warTag: args.warTag, clanTag: args.clanTag, maxAge });
169
+ const { data, res } = await this.rest.getClanWarLeagueRound(args.warTag, options);
170
+ return new struct_1.ClanWar(this, data, { warTag: args.warTag, clanTag: args.clanTag, maxAge: res.maxAge });
171
171
  }
172
172
  /** Get info about a player by tag. */
173
173
  async getPlayer(playerTag, options) {
@@ -155,7 +155,7 @@ class PollingClient extends Client_1.Client {
155
155
  if (!(this.listenerCount(Constants_1.PollingEvents.MaintenanceStart) && this.listenerCount(Constants_1.PollingEvents.MaintenanceEnd)))
156
156
  return;
157
157
  try {
158
- const res = await this.rest.getClans({ maxMembers: Math.floor(Math.random() * 40) + 10, limit: 1 });
158
+ const { res } = await this.rest.getClans({ maxMembers: Math.floor(Math.random() * 40) + 10, limit: 1 });
159
159
  if (res.status === 200 && this.inMaintenance) {
160
160
  this.inMaintenance = Boolean(false);
161
161
  const duration = Date.now() - this._maintenanceStartTime.getTime();
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  export * from './client/Client';
2
2
  export * from './client/PollingClient';
3
+ export * from './rest/HTTPError';
3
4
  export * from './rest/RESTManager';
4
5
  export * from './rest/RequestHandler';
5
- export * from './rest/HTTPError';
6
6
  export * from './rest/Throttler';
7
- export * from './util/Util';
8
7
  export * from './struct';
9
8
  export * from './types';
10
9
  export * from './util/Constants';
11
10
  export * from './util/Store';
11
+ export * from './util/Util';
package/dist/index.js CHANGED
@@ -16,12 +16,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./client/Client"), exports);
18
18
  __exportStar(require("./client/PollingClient"), exports);
19
+ __exportStar(require("./rest/HTTPError"), exports);
19
20
  __exportStar(require("./rest/RESTManager"), exports);
20
21
  __exportStar(require("./rest/RequestHandler"), exports);
21
- __exportStar(require("./rest/HTTPError"), exports);
22
22
  __exportStar(require("./rest/Throttler"), exports);
23
- __exportStar(require("./util/Util"), exports);
24
23
  __exportStar(require("./struct"), exports);
25
24
  __exportStar(require("./types"), exports);
26
25
  __exportStar(require("./util/Constants"), exports);
27
26
  __exportStar(require("./util/Store"), exports);
27
+ __exportStar(require("./util/Util"), exports);
package/dist/index.mjs CHANGED
@@ -65,3 +65,4 @@ export const Util = mod.Util;
65
65
  export const WarClan = mod.WarClan;
66
66
  export const WarLeagues = mod.WarLeagues;
67
67
  export const WarLogClan = mod.WarLogClan;
68
+ export const timeoutSignal = mod.timeoutSignal;
@@ -1,8 +1,8 @@
1
1
  /// <reference types="node" />
2
2
  import { EventEmitter } from 'node:events';
3
- import { Util } from '../util/Util';
4
- import { APIClan, APIClanList, APIClanMemberList, APICapitalRaidSeasons, APIClanRankingList, APIClanBuilderBaseRankingList, APIClanWar, APIClanWarLeagueGroup, APIClanWarLog, APIGoldPassSeason, APILabelList, APILeague, APILeagueList, APILeagueSeasonList, APILocation, APILocationList, APIPlayer, APIPlayerRankingList, APIPlayerSeasonRankingList, APIPlayerBuilderBaseRankingList, APIVerifyToken, APIWarLeague, APIWarLeagueList, SearchOptions, ClanSearchOptions, RESTOptions, OverrideOptions, LoginOptions, APICapitalLeagueList, APICapitalLeague, APIClanCapitalRankingList, APIBuilderBaseLeagueList, APIBuilderBaseLeague } from '../types';
3
+ import { APIBuilderBaseLeague, APIBuilderBaseLeagueList, APICapitalLeague, APICapitalLeagueList, APICapitalRaidSeasons, APIClan, APIClanBuilderBaseRankingList, APIClanCapitalRankingList, APIClanList, APIClanMemberList, APIClanRankingList, APIClanWar, APIClanWarLeagueGroup, APIClanWarLog, APIGoldPassSeason, APILabelList, APILeague, APILeagueList, APILeagueSeasonList, APILocation, APILocationList, APIPlayer, APIPlayerBuilderBaseRankingList, APIPlayerRankingList, APIPlayerSeasonRankingList, APIVerifyToken, APIWarLeague, APIWarLeagueList, ClanSearchOptions, LoginOptions, OverrideOptions, RESTOptions, SearchOptions } from '../types';
5
4
  import { RestEvents } from '../util/Constants';
5
+ import { Util } from '../util/Util';
6
6
  import { RequestHandler } from './RequestHandler';
7
7
  export interface IRestEvents {
8
8
  [RestEvents.Error]: [error: unknown];
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RESTManager = void 0;
4
4
  const node_events_1 = require("node:events");
5
- const Util_1 = require("../util/Util");
6
5
  const Constants_1 = require("../util/Constants");
6
+ const Util_1 = require("../util/Util");
7
7
  const RequestHandler_1 = require("./RequestHandler");
8
8
  /** Represents a REST Manager of the client. */
9
9
  class RESTManager extends node_events_1.EventEmitter {
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { EventEmitter } from 'node:events';
3
- import { Response, RequestOptions, LoginOptions, RequestHandlerOptions } from '../types';
3
+ import { LoginOptions, RequestHandlerOptions, RequestOptions, Response } from '../types';
4
4
  import { IRestEvents } from './RESTManager';
5
5
  export interface RequestHandler {
6
6
  emit: (<K extends keyof IRestEvents>(event: K, ...args: IRestEvents[K]) => boolean) & (<S extends string | symbol>(event: Exclude<S, keyof IRestEvents>, ...args: any[]) => boolean);
@@ -27,6 +27,7 @@ export interface RequestHandler {
27
27
  */
28
28
  rateLimited: string;
29
29
  }
30
+ export type ResponseBody = any;
30
31
  /** Represents the class that manages handlers for endpoints. */
31
32
  export declare class RequestHandler extends EventEmitter {
32
33
  #private;
@@ -42,6 +43,7 @@ export declare class RequestHandler extends EventEmitter {
42
43
  private readonly restRequestTimeout;
43
44
  private readonly throttler?;
44
45
  private readonly cached;
46
+ private readonly dispatcher;
45
47
  constructor(options?: RequestHandlerOptions);
46
48
  private get _keys();
47
49
  private get _key();
@@ -1,27 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
26
3
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
27
4
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
@@ -33,20 +10,16 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
33
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
34
11
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
35
12
  };
36
- var __importDefault = (this && this.__importDefault) || function (mod) {
37
- return (mod && mod.__esModule) ? mod : { "default": mod };
38
- };
39
13
  var _RequestHandler_keyIndex;
40
14
  Object.defineProperty(exports, "__esModule", { value: true });
41
15
  exports.RequestHandler = void 0;
42
- const node_https_1 = __importDefault(require("node:https"));
43
16
  const node_events_1 = require("node:events");
44
- const node_fetch_1 = __importStar(require("node-fetch"));
17
+ const undici_1 = require("undici");
45
18
  const Constants_1 = require("../util/Constants");
46
19
  const Store_1 = require("../util/Store");
20
+ const Util_1 = require("../util/Util");
47
21
  const HTTPError_1 = require("./HTTPError");
48
22
  const IP_REGEX = /\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}/g;
49
- const agent = new node_https_1.default.Agent({ keepAlive: true });
50
23
  /** Represents the class that manages handlers for endpoints. */
51
24
  class RequestHandler extends node_events_1.EventEmitter {
52
25
  constructor(options) {
@@ -62,6 +35,10 @@ class RequestHandler extends node_events_1.EventEmitter {
62
35
  this.cached = options.cache;
63
36
  else
64
37
  this.cached = options?.cache === true ? new Store_1.CacheStore() : null;
38
+ this.dispatcher = new undici_1.Pool(new URL(this.baseURL).origin, {
39
+ connections: options?.connections ?? null,
40
+ pipelining: options?.pipelining ?? 1
41
+ });
65
42
  }
66
43
  get _keys() {
67
44
  return Array.isArray(this.keys) ? this.keys : [this.keys];
@@ -81,7 +58,10 @@ class RequestHandler extends node_events_1.EventEmitter {
81
58
  async request(path, options = {}) {
82
59
  const cached = this.cached ? (await this.cached.get(path)) ?? null : null;
83
60
  if (cached && options.force !== true) {
84
- return { data: cached.data, maxAge: cached.ttl - Date.now(), status: cached.status, path, ok: cached.status === 200 };
61
+ return {
62
+ data: cached.data,
63
+ res: { maxAge: cached.ttl - Date.now(), status: cached.status, path, ok: cached.status === 200 }
64
+ };
85
65
  }
86
66
  if (!this.throttler || options.ignoreRateLimit)
87
67
  return this.exec(path, options);
@@ -90,44 +70,50 @@ class RequestHandler extends node_events_1.EventEmitter {
90
70
  }
91
71
  async exec(path, options = {}, retries = 0) {
92
72
  try {
93
- const res = await (0, node_fetch_1.default)(`${this.baseURL}${path}`, {
94
- agent,
73
+ const res = await this.dispatcher.request({
74
+ path: `/v1${path}`,
95
75
  body: options.body,
96
- method: options.method,
97
- timeout: options.restRequestTimeout ?? this.restRequestTimeout,
76
+ method: 'GET',
77
+ signal: (0, Util_1.timeoutSignal)(options.restRequestTimeout ?? this.restRequestTimeout),
98
78
  headers: { 'Authorization': `Bearer ${this._key}`, 'Content-Type': 'application/json' }
99
79
  });
100
- if (res.status === 504 && retries < (options.retryLimit ?? this.retryLimit)) {
80
+ if (res.statusCode === 504 && retries < (options.retryLimit ?? this.retryLimit)) {
101
81
  return await this.exec(path, options, ++retries);
102
82
  }
103
- const data = await res.json();
83
+ const data = (await res.body.json());
104
84
  if (this.creds &&
105
- res.status === 403 &&
106
- data.reason === 'accessDenied.invalidIp' &&
85
+ res.statusCode === 403 &&
86
+ data?.reason === 'accessDenied.invalidIp' &&
107
87
  retries < (options.retryLimit ?? this.retryLimit)) {
108
88
  const keys = await this.reValidateKeys().then(() => () => this.login());
109
89
  if (keys.length)
110
90
  return await this.exec(path, options, ++retries);
111
91
  }
112
- const maxAge = Number(res.headers.get('cache-control')?.split('=')?.[1] ?? 0) * 1000;
113
- if (res.status === 403 && !data?.message && this.rejectIfNotValid) {
114
- throw new HTTPError_1.HTTPError(HTTPError_1.PrivateWarLogError, res.status, path, maxAge);
92
+ const maxAge = Number(res.headers['cache-control']?.split('=')?.[1] ?? 0) * 1000;
93
+ if (res.statusCode === 403 && !data?.message && this.rejectIfNotValid) {
94
+ throw new HTTPError_1.HTTPError(HTTPError_1.PrivateWarLogError, res.statusCode, path, maxAge);
115
95
  }
116
- if (!res.ok && this.rejectIfNotValid) {
117
- throw new HTTPError_1.HTTPError(data, res.status, path, maxAge, options.method);
96
+ if (res.statusCode !== 200 && this.rejectIfNotValid) {
97
+ throw new HTTPError_1.HTTPError(data, res.statusCode, path, maxAge, options.method);
118
98
  }
119
- if (this.cached && maxAge > 0 && options.cache !== false && res.ok) {
120
- await this.cached.set(path, { data, ttl: Date.now() + maxAge, status: res.status }, maxAge);
99
+ if (this.cached && maxAge > 0 && options.cache !== false && res.statusCode === 200) {
100
+ await this.cached.set(path, { data, ttl: Date.now() + maxAge, status: res.statusCode }, maxAge);
121
101
  }
122
- return { data, maxAge, status: res.status, path, ok: res.status === 200 };
102
+ return {
103
+ data: data,
104
+ res: { maxAge, status: res.statusCode, path, ok: res.statusCode === 200 }
105
+ };
123
106
  }
124
107
  catch (error) {
125
- if (error instanceof node_fetch_1.FetchError && error.type === 'request-timeout' && retries < (options.retryLimit ?? this.retryLimit)) {
108
+ if (error.code === 'UND_ERR_ABORTED' && retries < (options.retryLimit ?? this.retryLimit)) {
126
109
  return this.exec(path, options, ++retries);
127
110
  }
128
111
  if (this.rejectIfNotValid)
129
112
  throw error;
130
- return { data: { message: error.message }, maxAge: 0, status: 500, path, ok: false };
113
+ return {
114
+ data: { message: error.message },
115
+ res: { maxAge: 0, status: 500, path, ok: false }
116
+ };
131
117
  }
132
118
  }
133
119
  async init(options) {
@@ -143,9 +129,9 @@ class RequestHandler extends node_events_1.EventEmitter {
143
129
  }
144
130
  async reValidateKeys() {
145
131
  for (const key of this.keys) {
146
- const res = await (0, node_fetch_1.default)(`${this.baseURL}/locations?limit=1`, {
132
+ const res = await (0, undici_1.fetch)(`${this.baseURL}/locations?limit=1`, {
147
133
  method: 'GET',
148
- timeout: this.restRequestTimeout,
134
+ signal: (0, Util_1.timeoutSignal)(this.restRequestTimeout),
149
135
  headers: { 'Authorization': `Bearer ${key}`, 'Content-Type': 'application/json' }
150
136
  }).catch(() => null);
151
137
  if (res?.status === 403) {
@@ -156,13 +142,13 @@ class RequestHandler extends node_events_1.EventEmitter {
156
142
  }
157
143
  }
158
144
  async login() {
159
- const res = await (0, node_fetch_1.default)(`${Constants_1.DevSiteAPIBaseURL}/login`, {
145
+ const res = await (0, undici_1.fetch)(`${Constants_1.DevSiteAPIBaseURL}/login`, {
160
146
  method: 'POST',
161
- timeout: this.restRequestTimeout,
147
+ signal: (0, Util_1.timeoutSignal)(this.restRequestTimeout),
162
148
  headers: { 'Content-Type': 'application/json' },
163
149
  body: JSON.stringify({ email: this.email, password: this.password })
164
150
  });
165
- const data = await res.json();
151
+ const data = (await res.json());
166
152
  if (!res.ok)
167
153
  throw new Error(`Invalid email or password. ${JSON.stringify(data)}`);
168
154
  const ip = await this.getIp(data.temporaryAPIToken);
@@ -171,12 +157,12 @@ class RequestHandler extends node_events_1.EventEmitter {
171
157
  return this.getKeys(res.headers.get('set-cookie'), ip);
172
158
  }
173
159
  async getKeys(cookie, ip) {
174
- const res = await (0, node_fetch_1.default)(`${Constants_1.DevSiteAPIBaseURL}/apikey/list`, {
160
+ const res = await (0, undici_1.fetch)(`${Constants_1.DevSiteAPIBaseURL}/apikey/list`, {
175
161
  method: 'POST',
176
- timeout: this.restRequestTimeout,
162
+ signal: (0, Util_1.timeoutSignal)(this.restRequestTimeout),
177
163
  headers: { 'Content-Type': 'application/json', cookie }
178
164
  });
179
- const data = await res.json();
165
+ const data = (await res.json());
180
166
  if (!res.ok)
181
167
  throw new Error(`Failed to retrieve the API Keys. ${JSON.stringify(data)}`);
182
168
  // Get all available keys from the developer site.
@@ -213,18 +199,18 @@ class RequestHandler extends node_events_1.EventEmitter {
213
199
  return this.keys;
214
200
  }
215
201
  async revokeKey(keyId, cookie) {
216
- const res = await (0, node_fetch_1.default)(`${Constants_1.DevSiteAPIBaseURL}/apikey/revoke`, {
202
+ const res = await (0, undici_1.fetch)(`${Constants_1.DevSiteAPIBaseURL}/apikey/revoke`, {
217
203
  method: 'POST',
218
- timeout: this.restRequestTimeout,
204
+ signal: (0, Util_1.timeoutSignal)(this.restRequestTimeout),
219
205
  body: JSON.stringify({ id: keyId }),
220
206
  headers: { 'Content-Type': 'application/json', cookie }
221
207
  });
222
208
  return res.ok;
223
209
  }
224
210
  async createKey(cookie, ip) {
225
- const res = await (0, node_fetch_1.default)(`${Constants_1.DevSiteAPIBaseURL}/apikey/create`, {
211
+ const res = await (0, undici_1.fetch)(`${Constants_1.DevSiteAPIBaseURL}/apikey/create`, {
226
212
  method: 'POST',
227
- timeout: this.restRequestTimeout,
213
+ signal: (0, Util_1.timeoutSignal)(this.restRequestTimeout),
228
214
  headers: { 'Content-Type': 'application/json', cookie },
229
215
  body: JSON.stringify({
230
216
  cidrRanges: [ip],
@@ -232,7 +218,7 @@ class RequestHandler extends node_events_1.EventEmitter {
232
218
  description: this.keyDescription ?? new Date().toUTCString()
233
219
  })
234
220
  });
235
- const data = await res.json();
221
+ const data = (await res.json());
236
222
  if (!res.ok)
237
223
  throw new Error(`Failed to create API Key. ${JSON.stringify(data)}`);
238
224
  return data.key;
@@ -244,7 +230,9 @@ class RequestHandler extends node_events_1.EventEmitter {
244
230
  return props.cidrs[0].match(IP_REGEX)[0];
245
231
  }
246
232
  catch {
247
- const body = await (0, node_fetch_1.default)('https://api.ipify.org', { timeout: this.restRequestTimeout }).then((res) => res.text());
233
+ const body = await (0, undici_1.fetch)('https://api.ipify.org', {
234
+ signal: (0, Util_1.timeoutSignal)(this.restRequestTimeout)
235
+ }).then((res) => res.text());
248
236
  return body.match(IP_REGEX)?.[0] ?? null;
249
237
  }
250
238
  }
@@ -1,10 +1,10 @@
1
- import { APICapitalLeague, APIChatLanguage, APIClan, APILabel, APIWarLeague, OverrideOptions } from '../types';
2
1
  import { Client } from '../client/Client';
3
- import { ClanMember } from './ClanMember';
4
- import type { Player } from './Player';
5
- import { Location } from './Location';
2
+ import { APICapitalLeague, APIChatLanguage, APIClan, APILabel, APIWarLeague, OverrideOptions } from '../types';
6
3
  import { Badge } from './Badge';
7
4
  import { ClanCapital } from './ClanCapital';
5
+ import { ClanMember } from './ClanMember';
6
+ import { Location } from './Location';
7
+ import type { Player } from './Player';
8
8
  /** Represents a Clan. */
9
9
  export declare class Clan {
10
10
  client: Client;
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Clan = void 0;
4
- const ClanMember_1 = require("./ClanMember");
5
- const Location_1 = require("./Location");
6
4
  const Badge_1 = require("./Badge");
7
5
  const ClanCapital_1 = require("./ClanCapital");
6
+ const ClanMember_1 = require("./ClanMember");
7
+ const Location_1 = require("./Location");
8
8
  /** Represents a Clan. */
9
9
  class Clan {
10
10
  constructor(client, data) {
@@ -1,5 +1,5 @@
1
- import { APIClanMember, APIPlayerHouse, OverrideOptions } from '../types';
2
1
  import { Client } from '../client/Client';
2
+ import { APIClanMember, APIPlayerHouse, OverrideOptions } from '../types';
3
3
  import { League } from './League';
4
4
  export declare class ClanMember {
5
5
  client: Client;
@@ -1,5 +1,5 @@
1
- import { APIClanWar, APIClanWarAttack, APIClanWarMember, APIWarClan } from '../types';
2
1
  import { Client } from '../client/Client';
2
+ import { APIClanWar, APIClanWarAttack, APIClanWarMember, APIWarClan } from '../types';
3
3
  import { Badge } from './Badge';
4
4
  /** Represents a Clash of Clans War Attack. */
5
5
  export declare class ClanWarAttack {
@@ -1,8 +1,8 @@
1
- import { APIClanWarLeagueClan, APIClanWarLeagueClanMember, APIClanWarLeagueGroup, APIClanWarLeagueRound, OverrideOptions } from '../types';
2
1
  import { Client } from '../client/Client';
2
+ import { APIClanWarLeagueClan, APIClanWarLeagueClanMember, APIClanWarLeagueGroup, APIClanWarLeagueRound, OverrideOptions } from '../types';
3
+ import { Badge } from './Badge';
3
4
  import { ClanWar } from './ClanWar';
4
5
  import { Player } from './Player';
5
- import { Badge } from './Badge';
6
6
  /** Represents a Clan War League member. */
7
7
  export declare class ClanWarLeagueClanMember {
8
8
  /** The member's name. */
@@ -46,7 +46,7 @@ export declare class ClanWarLeagueRound {
46
46
  export declare class ClanWarLeagueGroup {
47
47
  private readonly client;
48
48
  /** The CWL group's current war state. */
49
- state: 'preparation' | 'inWar' | 'ended';
49
+ state: 'preparation' | 'inWar' | 'ended' | 'notInWar';
50
50
  /** Season Id of this CWL group. */
51
51
  season: string;
52
52
  /** Returns all participating clans. */
@@ -54,6 +54,8 @@ export declare class ClanWarLeagueGroup {
54
54
  /** An array containing all war tags for each round. */
55
55
  rounds: ClanWarLeagueRound[];
56
56
  constructor(client: Client, data: APIClanWarLeagueGroup);
57
+ /** Whether the clan is not in CWL group. */
58
+ get isNotInWar(): boolean;
57
59
  /** Total number of rounds for this CWL. */
58
60
  get totalRounds(): number;
59
61
  /**
@@ -49,11 +49,16 @@ exports.ClanWarLeagueRound = ClanWarLeagueRound;
49
49
  class ClanWarLeagueGroup {
50
50
  constructor(client, data) {
51
51
  this.client = client;
52
- // @ts-expect-error
53
52
  this.state = data.state;
54
- this.season = data.season;
55
- this.clans = data.clans.map((clan) => new ClanWarLeagueClan(client, clan));
56
- this.rounds = data.rounds.map((round, i) => new ClanWarLeagueRound(round, i));
53
+ if (this.state !== 'notInWar') {
54
+ this.season = data.season;
55
+ this.clans = data.clans.map((clan) => new ClanWarLeagueClan(client, clan));
56
+ this.rounds = data.rounds.map((round, i) => new ClanWarLeagueRound(round, i));
57
+ }
58
+ }
59
+ /** Whether the clan is not in CWL group. */
60
+ get isNotInWar() {
61
+ return this.state === 'notInWar';
57
62
  }
58
63
  /** Total number of rounds for this CWL. */
59
64
  get totalRounds() {
@@ -1,5 +1,5 @@
1
- import { APIClanWarLogEntry, APIWarLogClan } from '../types';
2
1
  import { Client } from '../client/Client';
2
+ import { APIClanWarLogEntry, APIWarLogClan } from '../types';
3
3
  import { Badge } from './Badge';
4
4
  /**
5
5
  * Represents War Log Clan.
@@ -1,11 +1,11 @@
1
- import { APIPlayer, APIPlayerHouse, OverrideOptions } from '../types';
2
1
  import { Client } from '../client/Client';
3
- import { LegendStatistics } from './LegendStatistics';
2
+ import { APIPlayer, APIPlayerHouse, OverrideOptions } from '../types';
4
3
  import { Achievement } from './Achievement';
5
- import { Hero, Spell, Troop } from './Unit';
6
- import { PlayerClan } from './PlayerClan';
7
- import { League } from './League';
8
4
  import { Label } from './Label';
5
+ import { League } from './League';
6
+ import { LegendStatistics } from './LegendStatistics';
7
+ import { PlayerClan } from './PlayerClan';
8
+ import { Hero, Spell, Troop } from './Unit';
9
9
  /** Represents a Clash of Clans Player. */
10
10
  export declare class Player {
11
11
  client: Client;
@@ -2,12 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Player = void 0;
4
4
  const Constants_1 = require("../util/Constants");
5
- const LegendStatistics_1 = require("./LegendStatistics");
6
5
  const Achievement_1 = require("./Achievement");
7
- const Unit_1 = require("./Unit");
8
- const PlayerClan_1 = require("./PlayerClan");
9
- const League_1 = require("./League");
10
6
  const Label_1 = require("./Label");
7
+ const League_1 = require("./League");
8
+ const LegendStatistics_1 = require("./LegendStatistics");
9
+ const PlayerClan_1 = require("./PlayerClan");
10
+ const Unit_1 = require("./Unit");
11
11
  /** Represents a Clash of Clans Player. */
12
12
  class Player {
13
13
  constructor(client, data) {
@@ -1,5 +1,5 @@
1
- import { OverrideOptions, APIPlayerClan } from '../types';
2
1
  import { Client } from '../client/Client';
2
+ import { APIPlayerClan, OverrideOptions } from '../types';
3
3
  import { Badge } from './Badge';
4
4
  /** Represents a Player's clan. */
5
5
  export declare class PlayerClan {
@@ -1,9 +1,9 @@
1
- import { APIClanRanking, APIClanBuilderBaseRanking, APIPlayerRanking, APIPlayerBuilderBaseRanking } from '../types';
2
1
  import { Client } from '../client/Client';
3
- import { PlayerClan } from './PlayerClan';
4
- import { Location } from './Location';
5
- import { League } from './League';
2
+ import { APIClanBuilderBaseRanking, APIClanRanking, APIPlayerBuilderBaseRanking, APIPlayerRanking } from '../types';
6
3
  import { Badge } from './Badge';
4
+ import { League } from './League';
5
+ import { Location } from './Location';
6
+ import { PlayerClan } from './PlayerClan';
7
7
  /** Represents the Player of seasonal legend league leader-board ranking. */
8
8
  export declare class SeasonRankedPlayer {
9
9
  /** The player's name. */
@@ -2,10 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RankedClan = exports.RankedPlayer = exports.SeasonRankedPlayer = void 0;
4
4
  const Constants_1 = require("../util/Constants");
5
- const PlayerClan_1 = require("./PlayerClan");
6
- const Location_1 = require("./Location");
7
- const League_1 = require("./League");
8
5
  const Badge_1 = require("./Badge");
6
+ const League_1 = require("./League");
7
+ const Location_1 = require("./Location");
8
+ const PlayerClan_1 = require("./PlayerClan");
9
9
  /** Represents the Player of seasonal legend league leader-board ranking. */
10
10
  class SeasonRankedPlayer {
11
11
  constructor(client, data) {
@@ -1,4 +1,4 @@
1
- import { APIPlayerItem, APIPlayer } from '../types';
1
+ import { APIPlayer, APIPlayerItem } from '../types';
2
2
  /** Represents a Player's Unit. */
3
3
  export declare class Unit {
4
4
  /** The name of this unit. */
@@ -1,10 +1,12 @@
1
1
  export * from './Achievement';
2
2
  export * from './Badge';
3
+ export * from './CapitalRaidSeason';
3
4
  export * from './Clan';
5
+ export * from './ClanCapital';
4
6
  export * from './ClanMember';
5
7
  export * from './ClanWar';
6
- export * from './ClanWarLog';
7
8
  export * from './ClanWarLeagueGroup';
9
+ export * from './ClanWarLog';
8
10
  export * from './Icon';
9
11
  export * from './LegendStatistics';
10
12
  export * from './Location';
@@ -13,5 +15,3 @@ export * from './PlayerClan';
13
15
  export * from './Ranking';
14
16
  export * from './Season';
15
17
  export * from './Unit';
16
- export * from './ClanCapital';
17
- export * from './CapitalRaidSeason';
@@ -16,11 +16,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./Achievement"), exports);
18
18
  __exportStar(require("./Badge"), exports);
19
+ __exportStar(require("./CapitalRaidSeason"), exports);
19
20
  __exportStar(require("./Clan"), exports);
21
+ __exportStar(require("./ClanCapital"), exports);
20
22
  __exportStar(require("./ClanMember"), exports);
21
23
  __exportStar(require("./ClanWar"), exports);
22
- __exportStar(require("./ClanWarLog"), exports);
23
24
  __exportStar(require("./ClanWarLeagueGroup"), exports);
25
+ __exportStar(require("./ClanWarLog"), exports);
24
26
  __exportStar(require("./Icon"), exports);
25
27
  __exportStar(require("./LegendStatistics"), exports);
26
28
  __exportStar(require("./Location"), exports);
@@ -29,5 +31,3 @@ __exportStar(require("./PlayerClan"), exports);
29
31
  __exportStar(require("./Ranking"), exports);
30
32
  __exportStar(require("./Season"), exports);
31
33
  __exportStar(require("./Unit"), exports);
32
- __exportStar(require("./ClanCapital"), exports);
33
- __exportStar(require("./CapitalRaidSeason"), exports);
@@ -1,4 +1,4 @@
1
- import { QueueThrottler, BatchThrottler } from '../rest/Throttler';
1
+ import { BatchThrottler, QueueThrottler } from '../rest/Throttler';
2
2
  export interface Store<T = any> {
3
3
  set: (key: string, value: T, ttl?: number) => boolean | Promise<boolean>;
4
4
  get: (key: string) => T | null | Promise<T | null>;
@@ -50,6 +50,10 @@ export interface PollingClientOptions extends ClientOptions {
50
50
  export interface RequestHandlerOptions extends ClientOptions {
51
51
  /** Set this `false` to use `res.ok` property. */
52
52
  rejectIfNotValid?: boolean;
53
+ /** The max number of clients to create. null if no limit. Default null. */
54
+ connections?: number;
55
+ /** The amount of concurrent requests to be sent over the single TCP/TLS connection according to RFC7230. Default: 1 */
56
+ pipelining?: number;
53
57
  }
54
58
  /** Search options for request. */
55
59
  export interface SearchOptions extends OverrideOptions {
@@ -88,16 +92,18 @@ export interface RequestOptions extends OverrideOptions {
88
92
  method?: string;
89
93
  }
90
94
  export interface Response<T> {
91
- /** Whether the response is ok. */
92
- ok: boolean;
93
95
  /** The response body. */
94
96
  data: T;
95
- /** Path of the request for this response. */
96
- path: string;
97
- /** HTTP status code of this response. */
98
- status: number;
99
- /** The maxAge of this response. */
100
- maxAge: number;
97
+ res: {
98
+ /** Whether the response is ok. */
99
+ ok: boolean;
100
+ /** Path of the request for this response. */
101
+ path: string;
102
+ /** HTTP status code of this response. */
103
+ status: number;
104
+ /** The maxAge of this response. */
105
+ maxAge: number;
106
+ };
101
107
  }
102
108
  /**
103
109
  * Clan search options for a request.
@@ -1,4 +1,5 @@
1
1
  import { ClanSearchOptions, SearchOptions } from '../types';
2
+ export declare function timeoutSignal(timeout: number): AbortSignal;
2
3
  /** Contains various general-purpose utility methods. */
3
4
  export declare class Util extends null {
4
5
  /**
package/dist/util/Util.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Util = void 0;
3
+ exports.Util = exports.timeoutSignal = void 0;
4
4
  const Constants_1 = require("../util/Constants");
5
5
  const TAG_CHARACTERS = '0289PYLQGRJCUV';
6
6
  const params = [
@@ -16,6 +16,20 @@ const params = [
16
16
  'after',
17
17
  'before'
18
18
  ];
19
+ function timeoutSignal(timeout) {
20
+ if (!Number.isInteger(timeout)) {
21
+ throw new TypeError('Expected an integer for the timeout');
22
+ }
23
+ const controller = new AbortController();
24
+ if (timeout > 0) {
25
+ const timeoutId = setTimeout(() => {
26
+ controller.abort();
27
+ }, timeout);
28
+ timeoutId.unref();
29
+ }
30
+ return controller.signal;
31
+ }
32
+ exports.timeoutSignal = timeoutSignal;
19
33
  /** Contains various general-purpose utility methods. */
20
34
  class Util extends null {
21
35
  /**
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "clashofclans.js",
3
- "version": "3.1.2",
3
+ "version": "3.1.3-dev.048e4b9",
4
4
  "description": "JavaScript library for interacting with the Clash of Clans API",
5
- "author": "SUVAJIT <suvajit.me@gmail.com>",
5
+ "author": "https://clashofclans.js.org",
6
6
  "license": "MIT",
7
7
  "main": "dist/index.js",
8
8
  "exports": {
@@ -42,25 +42,22 @@
42
42
  }
43
43
  },
44
44
  "dependencies": {
45
- "node-fetch": "^2.6.7"
45
+ "undici": "^5.23.0"
46
46
  },
47
47
  "devDependencies": {
48
- "@types/node-fetch": "^2.5.12",
49
- "gen-esm-wrapper": "^1.1.3",
50
- "@types/node": "^18.6.4",
51
- "@typescript-eslint/eslint-plugin": "^5.4.0",
52
- "@typescript-eslint/parser": "^5.4.0",
48
+ "@types/node": "^18.17.5",
49
+ "@typescript-eslint/eslint-plugin": "^6.3.0",
50
+ "@typescript-eslint/parser": "^6.3.0",
53
51
  "dotenv": "^16.0.2",
54
- "eslint": "^8.3.0",
55
- "eslint-config-marine": "^9.0.6",
56
- "eslint-config-prettier": "^8.3.0",
57
- "eslint-plugin-import": "^2.26.0",
58
- "eslint-plugin-prettier": "^4.0.0",
59
- "prettier": "^2.4.1",
60
- "rimraf": "^3.0.2",
61
- "typescript": "^4.7.4"
52
+ "eslint": "^8.47.0",
53
+ "eslint-config-prettier": "^9.0.0",
54
+ "eslint-plugin-prettier": "^5.0.0",
55
+ "gen-esm-wrapper": "^1.1.3",
56
+ "prettier": "^3.0.1",
57
+ "rimraf": "^5.0.1",
58
+ "typescript": "^5.1.6"
62
59
  },
63
60
  "engines": {
64
- "node": ">=14.x"
61
+ "node": ">=16.x"
65
62
  }
66
63
  }