@blizzard-api/client 1.0.2 → 1.0.4

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
@@ -23,6 +23,8 @@ npm i @blizzard-api/client
23
23
 
24
24
  ```ts
25
25
  import { createBlizzardApiClient } from '@blizzard-api/client';
26
+ //or
27
+ import createBlizzardApiClient from '@blizzard-api/client';
26
28
  import { wow } from '@blizzard-api/wow';
27
29
 
28
30
  const client = await createBlizzardApiClient({
package/dist/index.cjs CHANGED
@@ -1,111 +1,19 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var querystring = require('querystring');
6
+ var core = require('@blizzard-api/core');
7
+ var axios = require('axios');
29
8
 
30
- // src/index.ts
31
- var src_exports = {};
32
- __export(src_exports, {
33
- createBlizzardApiClient: () => createBlizzardApiClient
34
- });
35
- module.exports = __toCommonJS(src_exports);
9
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
+
11
+ var axios__default = /*#__PURE__*/_interopDefault(axios);
36
12
 
37
13
  // src/client/client.ts
38
- var import_node_querystring = require("querystring");
39
- var import_core = require("@blizzard-api/core");
40
- var import_axios = __toESM(require("axios"), 1);
41
14
  var BlizzardApiClient = class {
15
+ axios = axios__default.default.create();
42
16
  defaults;
43
- constructor(options) {
44
- const { origin, locale } = (0, import_core.getBlizzardApi)(options.origin, options.locale);
45
- this.defaults = {
46
- key: options.key,
47
- secret: options.secret,
48
- token: options.token,
49
- origin,
50
- locale
51
- };
52
- }
53
- axios = import_axios.default.create();
54
- /**
55
- * Get the request URL.
56
- * @param resource The resource to fetch. See {@link Resource}.
57
- * @param options Client options. See {@link ClientOptions}.
58
- * @returns The request URL.
59
- */
60
- getRequestUrl(resource, options) {
61
- const config = { ...this.defaults, ...options };
62
- const endpoint = (0, import_core.getBlizzardApi)(config.origin, config.locale);
63
- const backslashSeparator = resource.path.startsWith("/") ? "" : "/";
64
- return `${endpoint.hostname}${backslashSeparator}${resource.path}`;
65
- }
66
- /**
67
- * Get the request configuration.
68
- * @param resource The resource to fetch. See {@link Resource}.
69
- * @param options Client options. See {@link ClientOptions}.
70
- * @param headers Additional headers to include in the request.
71
- * @returns The request configuration.
72
- */
73
- getRequestConfig(resource, options, headers) {
74
- const config = { ...this.defaults, ...options };
75
- const endpoint = (0, import_core.getBlizzardApi)(config.origin, config.locale);
76
- const namespace = resource.namespace ? { "Battlenet-Namespace": `${resource.namespace}-${endpoint.origin}` } : void 0;
77
- return {
78
- headers: {
79
- ...headers,
80
- ...namespace,
81
- "Content-Type": "application/json",
82
- Authorization: `Bearer ${config.token}`
83
- },
84
- params: {
85
- locale: endpoint.locale,
86
- ...resource.parameters
87
- }
88
- };
89
- }
90
- /**
91
- * Send a request to the Blizzard API.
92
- * @param resource The resource to fetch. See {@link Resource}.
93
- * @param options Client options. See {@link ClientOptions}.
94
- * @param headers Additional headers to include in the request.
95
- * @returns The response from the Blizzard API. See {@link ResourceResponse}.
96
- */
97
- async sendRequest(resource, options, headers) {
98
- const url = this.getRequestUrl(resource, options);
99
- const config = this.getRequestConfig(resource, options, headers);
100
- try {
101
- return await this.axios.get(url, config);
102
- } catch (error) {
103
- if ((0, import_axios.isAxiosError)(error)) {
104
- throw new import_axios.AxiosError(error.message, error.code);
105
- }
106
- throw error;
107
- }
108
- }
109
17
  /**
110
18
  * Get an access token.
111
19
  * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.
@@ -120,27 +28,20 @@ var BlizzardApiClient = class {
120
28
  * // => 'client-id'
121
29
  */
122
30
  getAccessToken = async (options) => {
123
- const { key, secret, origin } = { ...this.defaults, ...options };
31
+ const { key, origin, secret } = { ...this.defaults, ...options };
124
32
  return this.axios.post(`https://${origin}.battle.net/oauth/token`, void 0, {
125
- params: {
126
- grant_type: "client_credentials"
127
- },
128
33
  auth: {
129
- username: key,
130
- password: secret
34
+ password: secret,
35
+ username: key
131
36
  },
132
37
  headers: {
133
38
  "Content-Type": "application/json"
39
+ },
40
+ params: {
41
+ grant_type: "client_credentials"
134
42
  }
135
43
  });
136
44
  };
137
- /**
138
- * Set the access token.
139
- * @param token The access token.
140
- */
141
- setAccessToken = (token) => {
142
- this.defaults.token = token;
143
- };
144
45
  /**
145
46
  * Refresh the access token.
146
47
  * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.
@@ -159,6 +60,13 @@ var BlizzardApiClient = class {
159
60
  this.setAccessToken(response.data.access_token);
160
61
  return response;
161
62
  };
63
+ /**
64
+ * Set the access token.
65
+ * @param token The access token.
66
+ */
67
+ setAccessToken = (token) => {
68
+ this.defaults.token = token;
69
+ };
162
70
  /**
163
71
  * Validate an access token.
164
72
  * @param options The validate access token arguments. See {@link ValidateAccessTokenArguments}.
@@ -175,7 +83,7 @@ var BlizzardApiClient = class {
175
83
  }
176
84
  return await this.axios.post(
177
85
  `https://${origin}.battle.net/oauth/check_token`,
178
- (0, import_node_querystring.stringify)({ token }),
86
+ querystring.stringify({ token }),
179
87
  {
180
88
  headers: {
181
89
  "Content-Type": "application/x-www-form-urlencoded"
@@ -183,6 +91,71 @@ var BlizzardApiClient = class {
183
91
  }
184
92
  );
185
93
  };
94
+ constructor(options) {
95
+ const { locale, origin } = core.getBlizzardApi(options.origin, options.locale);
96
+ this.defaults = {
97
+ key: options.key,
98
+ locale,
99
+ origin,
100
+ secret: options.secret,
101
+ token: options.token
102
+ };
103
+ }
104
+ /**
105
+ * Get the request configuration.
106
+ * @param resource The resource to fetch. See {@link Resource}.
107
+ * @param options Client options. See {@link ClientOptions}.
108
+ * @param headers Additional headers to include in the request.
109
+ * @returns The request configuration.
110
+ */
111
+ getRequestConfig(resource, options, headers) {
112
+ const config = { ...this.defaults, ...options };
113
+ const endpoint = core.getBlizzardApi(config.origin, config.locale);
114
+ const namespace = resource.namespace ? { "Battlenet-Namespace": `${resource.namespace}-${endpoint.origin}` } : void 0;
115
+ return {
116
+ headers: {
117
+ ...headers,
118
+ ...namespace,
119
+ Authorization: `Bearer ${config.token}`,
120
+ "Content-Type": "application/json"
121
+ },
122
+ params: {
123
+ locale: endpoint.locale,
124
+ ...resource.parameters
125
+ }
126
+ };
127
+ }
128
+ /**
129
+ * Get the request URL.
130
+ * @param resource The resource to fetch. See {@link Resource}.
131
+ * @param options Client options. See {@link ClientOptions}.
132
+ * @returns The request URL.
133
+ */
134
+ getRequestUrl(resource, options) {
135
+ const config = { ...this.defaults, ...options };
136
+ const endpoint = core.getBlizzardApi(config.origin, config.locale);
137
+ const backslashSeparator = resource.path.startsWith("/") ? "" : "/";
138
+ return `${endpoint.hostname}${backslashSeparator}${resource.path}`;
139
+ }
140
+ /**
141
+ * Send a request to the Blizzard API.
142
+ * @param resource The resource to fetch. See {@link Resource}.
143
+ * @param options Client options. See {@link ClientOptions}.
144
+ * @param headers Additional headers to include in the request.
145
+ * @returns The response from the Blizzard API. See {@link ResourceResponse}.
146
+ */
147
+ async sendRequest(resource, options, headers) {
148
+ const url = this.getRequestUrl(resource, options);
149
+ const config = this.getRequestConfig(resource, options, headers);
150
+ try {
151
+ return await this.axios.get(url, config);
152
+ } catch (error) {
153
+ if (axios.isAxiosError(error)) {
154
+ throw new axios.AxiosError(error.message, error.code);
155
+ }
156
+ throw error;
157
+ }
158
+ }
186
159
  };
187
160
 
188
161
  // src/client/create-client.ts
@@ -226,8 +199,8 @@ var createBlizzardApiClient = async (options, onTokenRefresh = true) => {
226
199
  }
227
200
  return client;
228
201
  };
229
- // Annotate the CommonJS export names for ESM import in node:
230
- 0 && (module.exports = {
231
- createBlizzardApiClient
232
- });
202
+
203
+ exports.createBlizzardApiClient = createBlizzardApiClient;
204
+ exports.default = createBlizzardApiClient;
205
+ //# sourceMappingURL=out.js.map
233
206
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/client/client.ts","../src/client/create-client.ts"],"sourcesContent":["export { createBlizzardApiClient } from './client/create-client';\r\nexport * from './client/types';\r\n","import { stringify } from 'node:querystring';\r\nimport { getBlizzardApi } from '@blizzard-api/core';\r\nimport type { Origins, Locales, ResourceResponse, Resource } from '@blizzard-api/core';\r\nimport type { AxiosResponse } from 'axios';\r\nimport axios, { AxiosError, isAxiosError } from 'axios';\r\nimport type {\r\n AccessToken,\r\n AccessTokenRequestArguments,\r\n ClientOptions,\r\n IBlizzardApiClient,\r\n ValidateAccessTokenArguments,\r\n ValidateAccessTokenResponse,\r\n} from './types';\r\n\r\n/**\r\n * A Blizzard API client.\r\n * @implements IBlizzardApiClient\r\n * @class\r\n * @classdesc A client to interact with the Blizzard API.\r\n * @example\r\n * const client = new BlizzardApiClient({\r\n * key: 'client',\r\n * secret: 'secret',\r\n * origin: 'eu',\r\n * locale: 'en_GB',\r\n * token: 'access'\r\n * });\r\n */\r\nexport class BlizzardApiClient implements IBlizzardApiClient {\r\n public defaults: {\r\n key: string;\r\n secret: string;\r\n origin: Origins;\r\n locale: Locales;\r\n token?: string;\r\n };\r\n\r\n constructor(options: ClientOptions) {\r\n const { origin, locale } = getBlizzardApi(options.origin, options.locale);\r\n this.defaults = {\r\n key: options.key,\r\n secret: options.secret,\r\n token: options.token,\r\n origin: origin,\r\n locale: locale,\r\n };\r\n }\r\n\r\n private axios = axios.create();\r\n\r\n /**\r\n * Get the request URL.\r\n * @param resource The resource to fetch. See {@link Resource}.\r\n * @param options Client options. See {@link ClientOptions}.\r\n * @returns The request URL.\r\n */\r\n public getRequestUrl<T, Protected extends boolean = false>(\r\n resource: Resource<T, object, Protected>,\r\n options?: Partial<ClientOptions>,\r\n ) {\r\n const config = { ...this.defaults, ...options };\r\n const endpoint = getBlizzardApi(config.origin, config.locale);\r\n\r\n const backslashSeparator = resource.path.startsWith('/') ? '' : '/';\r\n\r\n return `${endpoint.hostname}${backslashSeparator}${resource.path}`;\r\n }\r\n\r\n /**\r\n * Get the request configuration.\r\n * @param resource The resource to fetch. See {@link Resource}.\r\n * @param options Client options. See {@link ClientOptions}.\r\n * @param headers Additional headers to include in the request.\r\n * @returns The request configuration.\r\n */\r\n public getRequestConfig<T, Protected extends boolean = false>(\r\n resource: Resource<T, object, Protected>,\r\n options?: Partial<ClientOptions>,\r\n headers?: Record<string, string>,\r\n ) {\r\n const config = { ...this.defaults, ...options };\r\n const endpoint = getBlizzardApi(config.origin, config.locale);\r\n\r\n const namespace = resource.namespace\r\n ? { 'Battlenet-Namespace': `${resource.namespace}-${endpoint.origin}` }\r\n : undefined;\r\n\r\n return {\r\n headers: {\r\n ...headers,\r\n ...namespace,\r\n 'Content-Type': 'application/json',\r\n Authorization: `Bearer ${config.token}`,\r\n },\r\n params: {\r\n locale: endpoint.locale,\r\n ...resource.parameters,\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Send a request to the Blizzard API.\r\n * @param resource The resource to fetch. See {@link Resource}.\r\n * @param options Client options. See {@link ClientOptions}.\r\n * @param headers Additional headers to include in the request.\r\n * @returns The response from the Blizzard API. See {@link ResourceResponse}.\r\n */\r\n public async sendRequest<T, Protected extends boolean = false>(\r\n resource: Resource<T, object, Protected>,\r\n options?: Partial<ClientOptions>,\r\n headers?: Record<string, string>,\r\n ): ResourceResponse<AxiosResponse<T>> {\r\n const url = this.getRequestUrl(resource, options);\r\n const config = this.getRequestConfig(resource, options, headers);\r\n\r\n try {\r\n return await this.axios.get<T>(url, config);\r\n } catch (error) {\r\n if (isAxiosError(error)) {\r\n throw new AxiosError(error.message, error.code);\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Get an access token.\r\n * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.\r\n * @returns The access token. See {@link AccessToken}.\r\n * @example\r\n * const response = await client.getAccessToken();\r\n * const { access_token, token_type, expires_in, sub } = response.data;\r\n * console.log(access_token, token_type, expires_in, sub);\r\n * // => 'access'\r\n * // => 'bearer'\r\n * // => 86399\r\n * // => 'client-id'\r\n */\r\n public getAccessToken = async (options?: AccessTokenRequestArguments): Promise<AxiosResponse<AccessToken>> => {\r\n const { key, secret, origin } = { ...this.defaults, ...options };\r\n return this.axios.post<AccessToken>(`https://${origin}.battle.net/oauth/token`, undefined, {\r\n params: {\r\n grant_type: 'client_credentials',\r\n },\r\n auth: {\r\n username: key,\r\n password: secret,\r\n },\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n });\r\n };\r\n\r\n /**\r\n * Set the access token.\r\n * @param token The access token.\r\n */\r\n public setAccessToken = (token: string): void => {\r\n this.defaults.token = token;\r\n };\r\n\r\n /**\r\n * Refresh the access token.\r\n * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.\r\n * @returns The access token. See {@link AccessToken}.\r\n * @example\r\n * const response = await client.refreshAccessToken();\r\n * const { access_token, token_type, expires_in, sub } = response.data;\r\n * console.log(access_token, token_type, expires_in, sub);\r\n * // => 'access'\r\n * // => 'bearer'\r\n * // => 86399\r\n * // => 'client-id'\r\n */\r\n public refreshAccessToken = async (options?: AccessTokenRequestArguments): Promise<AxiosResponse<AccessToken>> => {\r\n const response = await this.getAccessToken(options);\r\n this.setAccessToken(response.data.access_token);\r\n return response;\r\n };\r\n\r\n /**\r\n * Validate an access token.\r\n * @param options The validate access token arguments. See {@link ValidateAccessTokenArguments}.\r\n * @returns The response from the Blizzard API. See {@link ValidateAccessTokenResponse}.\r\n * @example\r\n * const response = await client.validateAccessToken({ token: 'access' });\r\n * console.log(response.data.client_id);\r\n * // => 'client-id'\r\n */\r\n public validateAccessToken = async (\r\n options?: ValidateAccessTokenArguments,\r\n ): Promise<AxiosResponse<ValidateAccessTokenResponse>> => {\r\n const { origin, token } = { ...this.defaults, ...options };\r\n\r\n if (!token) {\r\n throw new Error('No token has been set previously or been passed to the validateAccessToken method.');\r\n }\r\n\r\n return await this.axios.post<ValidateAccessTokenResponse>(\r\n `https://${origin}.battle.net/oauth/check_token`,\r\n stringify({ token }),\r\n {\r\n headers: {\r\n 'Content-Type': 'application/x-www-form-urlencoded',\r\n },\r\n },\r\n );\r\n };\r\n}\r\n","import { BlizzardApiClient } from './client';\r\nimport type { AccessToken, ClientOptions } from './types';\r\n\r\nconst getTokenExpiration = (expiresIn: number) => expiresIn * 1000 - 60_000;\r\n\r\n/**\r\n * Create a new Blizzard API client.\r\n * @param options Client options, see {@link ClientOptions} & https://develop.battle.net/documentation/guides/getting-started\r\n * @param onTokenRefresh Callback function to handle token refresh. If set to `true`, the client will automatically refresh the token. If set to `false`, the client will not refresh the token. If set to a function, the function will be called with the new token.\r\n * @returns A new Blizzard API client.\r\n */\r\nexport const createBlizzardApiClient = async (\r\n options: ClientOptions,\r\n onTokenRefresh: boolean | ((token: AccessToken) => void) = true,\r\n): Promise<BlizzardApiClient> => {\r\n const { key, secret, token } = options;\r\n if (!key) {\r\n throw new Error(`Client missing 'key' parameter`);\r\n }\r\n if (!secret) {\r\n throw new Error(`Client missing 'secret' parameter`);\r\n }\r\n\r\n const client = new BlizzardApiClient(options);\r\n\r\n const refreshToken = async () => {\r\n const response = await client.getAccessToken();\r\n\r\n client.setAccessToken(response.data.access_token);\r\n\r\n if (typeof onTokenRefresh === 'function') {\r\n onTokenRefresh?.(response.data);\r\n }\r\n\r\n //Schedule a refresh of the token\r\n const timeout = setTimeout(() => void refreshToken(), getTokenExpiration(response.data.expires_in));\r\n timeout.unref();\r\n };\r\n\r\n //If tokenRefresh is false, return the client without refreshing the token\r\n if (!onTokenRefresh) {\r\n return client;\r\n }\r\n\r\n if (token) {\r\n try {\r\n //If token is set, validate the token\r\n const validatedToken = await client.validateAccessToken({ token });\r\n const expiry = getTokenExpiration(validatedToken.data.exp);\r\n //If token is expiring in less than 60 seconds, refresh the token\r\n if (expiry - Date.now() < 60_000) {\r\n await refreshToken();\r\n } else {\r\n //If token is not expiring, schedule a refresh\r\n const timeout = setTimeout(() => void refreshToken(), expiry - Date.now());\r\n //Unref the timeout so the process can exit\r\n timeout.unref();\r\n }\r\n } catch {\r\n //If token is invalid, refresh the token\r\n await refreshToken();\r\n }\r\n } else {\r\n //If token is not set, refresh the token\r\n await refreshToken();\r\n }\r\n\r\n return client;\r\n};\r\n"],"mappings":"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","names":["axios"]}
1
+ {"version":3,"sources":["../src/client/client.ts","../src/client/create-client.ts"],"names":[],"mappings":"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","sourcesContent":["import { stringify } from 'node:querystring';\r\nimport { getBlizzardApi } from '@blizzard-api/core';\r\nimport type { Locales, Origins, Resource, ResourceResponse } from '@blizzard-api/core';\r\nimport type { AxiosResponse } from 'axios';\r\nimport axios, { AxiosError, isAxiosError } from 'axios';\r\nimport type {\r\n AccessToken,\r\n AccessTokenRequestArguments,\r\n ClientOptions,\r\n IBlizzardApiClient,\r\n ValidateAccessTokenArguments,\r\n ValidateAccessTokenResponse,\r\n} from './types';\r\n\r\n/**\r\n * A Blizzard API client.\r\n * @implements IBlizzardApiClient\r\n * @class\r\n * @classdesc A client to interact with the Blizzard API.\r\n * @example\r\n * const client = new BlizzardApiClient({\r\n * key: 'client',\r\n * secret: 'secret',\r\n * origin: 'eu',\r\n * locale: 'en_GB',\r\n * token: 'access'\r\n * });\r\n */\r\nexport class BlizzardApiClient implements IBlizzardApiClient {\r\n private axios = axios.create();\r\n\r\n public defaults: {\r\n key: string;\r\n locale: Locales;\r\n origin: Origins;\r\n secret: string;\r\n token?: string;\r\n };\r\n\r\n /**\r\n * Get an access token.\r\n * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.\r\n * @returns The access token. See {@link AccessToken}.\r\n * @example\r\n * const response = await client.getAccessToken();\r\n * const { access_token, token_type, expires_in, sub } = response.data;\r\n * console.log(access_token, token_type, expires_in, sub);\r\n * // => 'access'\r\n * // => 'bearer'\r\n * // => 86399\r\n * // => 'client-id'\r\n */\r\n public getAccessToken = async (options?: AccessTokenRequestArguments): Promise<AxiosResponse<AccessToken>> => {\r\n const { key, origin, secret } = { ...this.defaults, ...options };\r\n return this.axios.post<AccessToken>(`https://${origin}.battle.net/oauth/token`, undefined, {\r\n auth: {\r\n password: secret,\r\n username: key,\r\n },\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n params: {\r\n grant_type: 'client_credentials',\r\n },\r\n });\r\n };\r\n\r\n /**\r\n * Refresh the access token.\r\n * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.\r\n * @returns The access token. See {@link AccessToken}.\r\n * @example\r\n * const response = await client.refreshAccessToken();\r\n * const { access_token, token_type, expires_in, sub } = response.data;\r\n * console.log(access_token, token_type, expires_in, sub);\r\n * // => 'access'\r\n * // => 'bearer'\r\n * // => 86399\r\n * // => 'client-id'\r\n */\r\n public refreshAccessToken = async (options?: AccessTokenRequestArguments): Promise<AxiosResponse<AccessToken>> => {\r\n const response = await this.getAccessToken(options);\r\n this.setAccessToken(response.data.access_token);\r\n return response;\r\n };\r\n\r\n /**\r\n * Set the access token.\r\n * @param token The access token.\r\n */\r\n public setAccessToken = (token: string): void => {\r\n this.defaults.token = token;\r\n };\r\n\r\n /**\r\n * Validate an access token.\r\n * @param options The validate access token arguments. See {@link ValidateAccessTokenArguments}.\r\n * @returns The response from the Blizzard API. See {@link ValidateAccessTokenResponse}.\r\n * @example\r\n * const response = await client.validateAccessToken({ token: 'access' });\r\n * console.log(response.data.client_id);\r\n * // => 'client-id'\r\n */\r\n public validateAccessToken = async (\r\n options?: ValidateAccessTokenArguments,\r\n ): Promise<AxiosResponse<ValidateAccessTokenResponse>> => {\r\n const { origin, token } = { ...this.defaults, ...options };\r\n\r\n if (!token) {\r\n throw new Error('No token has been set previously or been passed to the validateAccessToken method.');\r\n }\r\n\r\n return await this.axios.post<ValidateAccessTokenResponse>(\r\n `https://${origin}.battle.net/oauth/check_token`,\r\n stringify({ token }),\r\n {\r\n headers: {\r\n 'Content-Type': 'application/x-www-form-urlencoded',\r\n },\r\n },\r\n );\r\n };\r\n\r\n constructor(options: ClientOptions) {\r\n const { locale, origin } = getBlizzardApi(options.origin, options.locale);\r\n this.defaults = {\r\n key: options.key,\r\n locale: locale,\r\n origin: origin,\r\n secret: options.secret,\r\n token: options.token,\r\n };\r\n }\r\n\r\n /**\r\n * Get the request configuration.\r\n * @param resource The resource to fetch. See {@link Resource}.\r\n * @param options Client options. See {@link ClientOptions}.\r\n * @param headers Additional headers to include in the request.\r\n * @returns The request configuration.\r\n */\r\n public getRequestConfig<T, Protected extends boolean = false>(\r\n resource: Resource<T, object, Protected>,\r\n options?: Partial<ClientOptions>,\r\n headers?: Record<string, string>,\r\n ) {\r\n const config = { ...this.defaults, ...options };\r\n const endpoint = getBlizzardApi(config.origin, config.locale);\r\n\r\n const namespace = resource.namespace\r\n ? { 'Battlenet-Namespace': `${resource.namespace}-${endpoint.origin}` }\r\n : undefined;\r\n\r\n return {\r\n headers: {\r\n ...headers,\r\n ...namespace,\r\n Authorization: `Bearer ${config.token}`,\r\n 'Content-Type': 'application/json',\r\n },\r\n params: {\r\n locale: endpoint.locale,\r\n ...resource.parameters,\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Get the request URL.\r\n * @param resource The resource to fetch. See {@link Resource}.\r\n * @param options Client options. See {@link ClientOptions}.\r\n * @returns The request URL.\r\n */\r\n public getRequestUrl<T, Protected extends boolean = false>(\r\n resource: Resource<T, object, Protected>,\r\n options?: Partial<ClientOptions>,\r\n ) {\r\n const config = { ...this.defaults, ...options };\r\n const endpoint = getBlizzardApi(config.origin, config.locale);\r\n\r\n const backslashSeparator = resource.path.startsWith('/') ? '' : '/';\r\n\r\n return `${endpoint.hostname}${backslashSeparator}${resource.path}`;\r\n }\r\n\r\n /**\r\n * Send a request to the Blizzard API.\r\n * @param resource The resource to fetch. See {@link Resource}.\r\n * @param options Client options. See {@link ClientOptions}.\r\n * @param headers Additional headers to include in the request.\r\n * @returns The response from the Blizzard API. See {@link ResourceResponse}.\r\n */\r\n public async sendRequest<T, Protected extends boolean = false>(\r\n resource: Resource<T, object, Protected>,\r\n options?: Partial<ClientOptions>,\r\n headers?: Record<string, string>,\r\n ): ResourceResponse<AxiosResponse<T>> {\r\n const url = this.getRequestUrl(resource, options);\r\n const config = this.getRequestConfig(resource, options, headers);\r\n\r\n try {\r\n return await this.axios.get<T>(url, config);\r\n } catch (error) {\r\n if (isAxiosError(error)) {\r\n throw new AxiosError(error.message, error.code);\r\n }\r\n throw error;\r\n }\r\n }\r\n}\r\n","import { BlizzardApiClient } from './client';\r\nimport type { AccessToken, ClientOptions } from './types';\r\n\r\nconst getTokenExpiration = (expiresIn: number) => expiresIn * 1000 - 60_000;\r\n\r\n/**\r\n * Create a new Blizzard API client.\r\n * @param options Client options, see {@link ClientOptions} & https://develop.battle.net/documentation/guides/getting-started\r\n * @param onTokenRefresh Callback function to handle token refresh. If set to `true`, the client will automatically refresh the token. If set to `false`, the client will not refresh the token. If set to a function, the function will be called with the new token.\r\n * @returns A new Blizzard API client.\r\n */\r\nexport const createBlizzardApiClient = async (\r\n options: ClientOptions,\r\n onTokenRefresh: ((token: AccessToken) => void) | boolean = true,\r\n): Promise<BlizzardApiClient> => {\r\n const { key, secret, token } = options;\r\n if (!key) {\r\n throw new Error(`Client missing 'key' parameter`);\r\n }\r\n if (!secret) {\r\n throw new Error(`Client missing 'secret' parameter`);\r\n }\r\n\r\n const client = new BlizzardApiClient(options);\r\n\r\n const refreshToken = async () => {\r\n const response = await client.getAccessToken();\r\n\r\n client.setAccessToken(response.data.access_token);\r\n\r\n if (typeof onTokenRefresh === 'function') {\r\n onTokenRefresh?.(response.data);\r\n }\r\n\r\n //Schedule a refresh of the token\r\n const timeout = setTimeout(() => void refreshToken(), getTokenExpiration(response.data.expires_in));\r\n timeout.unref();\r\n };\r\n\r\n //If tokenRefresh is false, return the client without refreshing the token\r\n if (!onTokenRefresh) {\r\n return client;\r\n }\r\n\r\n if (token) {\r\n try {\r\n //If token is set, validate the token\r\n const validatedToken = await client.validateAccessToken({ token });\r\n const expiry = getTokenExpiration(validatedToken.data.exp);\r\n //If token is expiring in less than 60 seconds, refresh the token\r\n if (expiry - Date.now() < 60_000) {\r\n await refreshToken();\r\n } else {\r\n //If token is not expiring, schedule a refresh\r\n const timeout = setTimeout(() => void refreshToken(), expiry - Date.now());\r\n //Unref the timeout so the process can exit\r\n timeout.unref();\r\n }\r\n } catch {\r\n //If token is invalid, refresh the token\r\n await refreshToken();\r\n }\r\n } else {\r\n //If token is not set, refresh the token\r\n await refreshToken();\r\n }\r\n\r\n return client;\r\n};\r\n"]}
package/dist/index.d.cts CHANGED
@@ -20,9 +20,9 @@ import { AxiosResponse } from 'axios';
20
20
  */
21
21
  interface AccessToken {
22
22
  access_token: string;
23
- token_type: 'bearer';
24
23
  expires_in: number;
25
24
  sub?: string;
25
+ token_type: 'bearer';
26
26
  }
27
27
  /**
28
28
  * An access token request.
@@ -39,8 +39,8 @@ interface AccessToken {
39
39
  * };
40
40
  */
41
41
  interface AccessTokenRequestArguments {
42
- origin?: Origins;
43
42
  key?: string;
43
+ origin?: Origins;
44
44
  secret?: string;
45
45
  }
46
46
  /**
@@ -80,12 +80,12 @@ interface ValidateAccessTokenArguments {
80
80
  * };
81
81
  */
82
82
  interface ValidateAccessTokenResponse {
83
- scope: Array<string>;
84
83
  account_authorities: Array<unknown>;
85
- exp: number;
86
- client_authorities: Array<unknown>;
87
84
  authorities: Array<string>;
85
+ client_authorities: Array<unknown>;
88
86
  client_id: string;
87
+ exp: number;
88
+ scope: Array<string>;
89
89
  }
90
90
  /**
91
91
  * A client configuration object.
@@ -106,9 +106,9 @@ interface ValidateAccessTokenResponse {
106
106
  */
107
107
  interface ClientOptions {
108
108
  key: string;
109
- secret: string;
110
- origin: Origins;
111
109
  locale?: Locales;
110
+ origin: Origins;
111
+ secret: string;
112
112
  token?: string;
113
113
  }
114
114
  /**
@@ -121,8 +121,8 @@ interface ClientOptions {
121
121
  */
122
122
  interface IBlizzardApiClient {
123
123
  getAccessToken: (options: AccessTokenRequestArguments) => Promise<AxiosResponse<AccessToken>>;
124
- setAccessToken: (token: string) => void;
125
124
  refreshAccessToken: (options: AccessTokenRequestArguments) => Promise<AxiosResponse<AccessToken>>;
125
+ setAccessToken: (token: string) => void;
126
126
  validateAccessToken: (options: ValidateAccessTokenArguments) => Promise<AxiosResponse<ValidateAccessTokenResponse>>;
127
127
  }
128
128
 
@@ -141,47 +141,14 @@ interface IBlizzardApiClient {
141
141
  * });
142
142
  */
143
143
  declare class BlizzardApiClient implements IBlizzardApiClient {
144
+ private axios;
144
145
  defaults: {
145
146
  key: string;
146
- secret: string;
147
- origin: Origins;
148
147
  locale: Locales;
148
+ origin: Origins;
149
+ secret: string;
149
150
  token?: string;
150
151
  };
151
- constructor(options: ClientOptions);
152
- private axios;
153
- /**
154
- * Get the request URL.
155
- * @param resource The resource to fetch. See {@link Resource}.
156
- * @param options Client options. See {@link ClientOptions}.
157
- * @returns The request URL.
158
- */
159
- getRequestUrl<T, Protected extends boolean = false>(resource: Resource<T, object, Protected>, options?: Partial<ClientOptions>): string;
160
- /**
161
- * Get the request configuration.
162
- * @param resource The resource to fetch. See {@link Resource}.
163
- * @param options Client options. See {@link ClientOptions}.
164
- * @param headers Additional headers to include in the request.
165
- * @returns The request configuration.
166
- */
167
- getRequestConfig<T, Protected extends boolean = false>(resource: Resource<T, object, Protected>, options?: Partial<ClientOptions>, headers?: Record<string, string>): {
168
- headers: {
169
- 'Content-Type': string;
170
- Authorization: string;
171
- 'Battlenet-Namespace'?: string | undefined;
172
- };
173
- params: {
174
- locale: "en_US" | "es_MX" | "pt_BR" | "en_GB" | "es_ES" | "fr_FR" | "ru_RU" | "de_DE" | "pt_PT" | "it_IT" | "ko_KR" | "zh_TW" | "zh_CN" | "multi";
175
- };
176
- };
177
- /**
178
- * Send a request to the Blizzard API.
179
- * @param resource The resource to fetch. See {@link Resource}.
180
- * @param options Client options. See {@link ClientOptions}.
181
- * @param headers Additional headers to include in the request.
182
- * @returns The response from the Blizzard API. See {@link ResourceResponse}.
183
- */
184
- sendRequest<T, Protected extends boolean = false>(resource: Resource<T, object, Protected>, options?: Partial<ClientOptions>, headers?: Record<string, string>): ResourceResponse<AxiosResponse<T>>;
185
152
  /**
186
153
  * Get an access token.
187
154
  * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.
@@ -196,11 +163,6 @@ declare class BlizzardApiClient implements IBlizzardApiClient {
196
163
  * // => 'client-id'
197
164
  */
198
165
  getAccessToken: (options?: AccessTokenRequestArguments) => Promise<AxiosResponse<AccessToken>>;
199
- /**
200
- * Set the access token.
201
- * @param token The access token.
202
- */
203
- setAccessToken: (token: string) => void;
204
166
  /**
205
167
  * Refresh the access token.
206
168
  * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.
@@ -215,6 +177,11 @@ declare class BlizzardApiClient implements IBlizzardApiClient {
215
177
  * // => 'client-id'
216
178
  */
217
179
  refreshAccessToken: (options?: AccessTokenRequestArguments) => Promise<AxiosResponse<AccessToken>>;
180
+ /**
181
+ * Set the access token.
182
+ * @param token The access token.
183
+ */
184
+ setAccessToken: (token: string) => void;
218
185
  /**
219
186
  * Validate an access token.
220
187
  * @param options The validate access token arguments. See {@link ValidateAccessTokenArguments}.
@@ -225,6 +192,39 @@ declare class BlizzardApiClient implements IBlizzardApiClient {
225
192
  * // => 'client-id'
226
193
  */
227
194
  validateAccessToken: (options?: ValidateAccessTokenArguments) => Promise<AxiosResponse<ValidateAccessTokenResponse>>;
195
+ constructor(options: ClientOptions);
196
+ /**
197
+ * Get the request configuration.
198
+ * @param resource The resource to fetch. See {@link Resource}.
199
+ * @param options Client options. See {@link ClientOptions}.
200
+ * @param headers Additional headers to include in the request.
201
+ * @returns The request configuration.
202
+ */
203
+ getRequestConfig<T, Protected extends boolean = false>(resource: Resource<T, object, Protected>, options?: Partial<ClientOptions>, headers?: Record<string, string>): {
204
+ headers: {
205
+ Authorization: string;
206
+ 'Content-Type': string;
207
+ 'Battlenet-Namespace'?: string | undefined;
208
+ };
209
+ params: {
210
+ locale: "de_DE" | "en_GB" | "en_US" | "es_ES" | "es_MX" | "fr_FR" | "it_IT" | "ko_KR" | "multi" | "pt_BR" | "pt_PT" | "ru_RU" | "zh_CN" | "zh_TW";
211
+ };
212
+ };
213
+ /**
214
+ * Get the request URL.
215
+ * @param resource The resource to fetch. See {@link Resource}.
216
+ * @param options Client options. See {@link ClientOptions}.
217
+ * @returns The request URL.
218
+ */
219
+ getRequestUrl<T, Protected extends boolean = false>(resource: Resource<T, object, Protected>, options?: Partial<ClientOptions>): string;
220
+ /**
221
+ * Send a request to the Blizzard API.
222
+ * @param resource The resource to fetch. See {@link Resource}.
223
+ * @param options Client options. See {@link ClientOptions}.
224
+ * @param headers Additional headers to include in the request.
225
+ * @returns The response from the Blizzard API. See {@link ResourceResponse}.
226
+ */
227
+ sendRequest<T, Protected extends boolean = false>(resource: Resource<T, object, Protected>, options?: Partial<ClientOptions>, headers?: Record<string, string>): ResourceResponse<AxiosResponse<T>>;
228
228
  }
229
229
 
230
230
  /**
@@ -233,6 +233,6 @@ declare class BlizzardApiClient implements IBlizzardApiClient {
233
233
  * @param onTokenRefresh Callback function to handle token refresh. If set to `true`, the client will automatically refresh the token. If set to `false`, the client will not refresh the token. If set to a function, the function will be called with the new token.
234
234
  * @returns A new Blizzard API client.
235
235
  */
236
- declare const createBlizzardApiClient: (options: ClientOptions, onTokenRefresh?: boolean | ((token: AccessToken) => void)) => Promise<BlizzardApiClient>;
236
+ declare const createBlizzardApiClient: (options: ClientOptions, onTokenRefresh?: ((token: AccessToken) => void) | boolean) => Promise<BlizzardApiClient>;
237
237
 
238
- export { type AccessToken, type AccessTokenRequestArguments, type ClientOptions, type IBlizzardApiClient, type ValidateAccessTokenArguments, type ValidateAccessTokenResponse, createBlizzardApiClient };
238
+ export { type AccessToken, type AccessTokenRequestArguments, type ClientOptions, type IBlizzardApiClient, type ValidateAccessTokenArguments, type ValidateAccessTokenResponse, createBlizzardApiClient, createBlizzardApiClient as default };
package/dist/index.d.ts CHANGED
@@ -20,9 +20,9 @@ import { AxiosResponse } from 'axios';
20
20
  */
21
21
  interface AccessToken {
22
22
  access_token: string;
23
- token_type: 'bearer';
24
23
  expires_in: number;
25
24
  sub?: string;
25
+ token_type: 'bearer';
26
26
  }
27
27
  /**
28
28
  * An access token request.
@@ -39,8 +39,8 @@ interface AccessToken {
39
39
  * };
40
40
  */
41
41
  interface AccessTokenRequestArguments {
42
- origin?: Origins;
43
42
  key?: string;
43
+ origin?: Origins;
44
44
  secret?: string;
45
45
  }
46
46
  /**
@@ -80,12 +80,12 @@ interface ValidateAccessTokenArguments {
80
80
  * };
81
81
  */
82
82
  interface ValidateAccessTokenResponse {
83
- scope: Array<string>;
84
83
  account_authorities: Array<unknown>;
85
- exp: number;
86
- client_authorities: Array<unknown>;
87
84
  authorities: Array<string>;
85
+ client_authorities: Array<unknown>;
88
86
  client_id: string;
87
+ exp: number;
88
+ scope: Array<string>;
89
89
  }
90
90
  /**
91
91
  * A client configuration object.
@@ -106,9 +106,9 @@ interface ValidateAccessTokenResponse {
106
106
  */
107
107
  interface ClientOptions {
108
108
  key: string;
109
- secret: string;
110
- origin: Origins;
111
109
  locale?: Locales;
110
+ origin: Origins;
111
+ secret: string;
112
112
  token?: string;
113
113
  }
114
114
  /**
@@ -121,8 +121,8 @@ interface ClientOptions {
121
121
  */
122
122
  interface IBlizzardApiClient {
123
123
  getAccessToken: (options: AccessTokenRequestArguments) => Promise<AxiosResponse<AccessToken>>;
124
- setAccessToken: (token: string) => void;
125
124
  refreshAccessToken: (options: AccessTokenRequestArguments) => Promise<AxiosResponse<AccessToken>>;
125
+ setAccessToken: (token: string) => void;
126
126
  validateAccessToken: (options: ValidateAccessTokenArguments) => Promise<AxiosResponse<ValidateAccessTokenResponse>>;
127
127
  }
128
128
 
@@ -141,47 +141,14 @@ interface IBlizzardApiClient {
141
141
  * });
142
142
  */
143
143
  declare class BlizzardApiClient implements IBlizzardApiClient {
144
+ private axios;
144
145
  defaults: {
145
146
  key: string;
146
- secret: string;
147
- origin: Origins;
148
147
  locale: Locales;
148
+ origin: Origins;
149
+ secret: string;
149
150
  token?: string;
150
151
  };
151
- constructor(options: ClientOptions);
152
- private axios;
153
- /**
154
- * Get the request URL.
155
- * @param resource The resource to fetch. See {@link Resource}.
156
- * @param options Client options. See {@link ClientOptions}.
157
- * @returns The request URL.
158
- */
159
- getRequestUrl<T, Protected extends boolean = false>(resource: Resource<T, object, Protected>, options?: Partial<ClientOptions>): string;
160
- /**
161
- * Get the request configuration.
162
- * @param resource The resource to fetch. See {@link Resource}.
163
- * @param options Client options. See {@link ClientOptions}.
164
- * @param headers Additional headers to include in the request.
165
- * @returns The request configuration.
166
- */
167
- getRequestConfig<T, Protected extends boolean = false>(resource: Resource<T, object, Protected>, options?: Partial<ClientOptions>, headers?: Record<string, string>): {
168
- headers: {
169
- 'Content-Type': string;
170
- Authorization: string;
171
- 'Battlenet-Namespace'?: string | undefined;
172
- };
173
- params: {
174
- locale: "en_US" | "es_MX" | "pt_BR" | "en_GB" | "es_ES" | "fr_FR" | "ru_RU" | "de_DE" | "pt_PT" | "it_IT" | "ko_KR" | "zh_TW" | "zh_CN" | "multi";
175
- };
176
- };
177
- /**
178
- * Send a request to the Blizzard API.
179
- * @param resource The resource to fetch. See {@link Resource}.
180
- * @param options Client options. See {@link ClientOptions}.
181
- * @param headers Additional headers to include in the request.
182
- * @returns The response from the Blizzard API. See {@link ResourceResponse}.
183
- */
184
- sendRequest<T, Protected extends boolean = false>(resource: Resource<T, object, Protected>, options?: Partial<ClientOptions>, headers?: Record<string, string>): ResourceResponse<AxiosResponse<T>>;
185
152
  /**
186
153
  * Get an access token.
187
154
  * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.
@@ -196,11 +163,6 @@ declare class BlizzardApiClient implements IBlizzardApiClient {
196
163
  * // => 'client-id'
197
164
  */
198
165
  getAccessToken: (options?: AccessTokenRequestArguments) => Promise<AxiosResponse<AccessToken>>;
199
- /**
200
- * Set the access token.
201
- * @param token The access token.
202
- */
203
- setAccessToken: (token: string) => void;
204
166
  /**
205
167
  * Refresh the access token.
206
168
  * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.
@@ -215,6 +177,11 @@ declare class BlizzardApiClient implements IBlizzardApiClient {
215
177
  * // => 'client-id'
216
178
  */
217
179
  refreshAccessToken: (options?: AccessTokenRequestArguments) => Promise<AxiosResponse<AccessToken>>;
180
+ /**
181
+ * Set the access token.
182
+ * @param token The access token.
183
+ */
184
+ setAccessToken: (token: string) => void;
218
185
  /**
219
186
  * Validate an access token.
220
187
  * @param options The validate access token arguments. See {@link ValidateAccessTokenArguments}.
@@ -225,6 +192,39 @@ declare class BlizzardApiClient implements IBlizzardApiClient {
225
192
  * // => 'client-id'
226
193
  */
227
194
  validateAccessToken: (options?: ValidateAccessTokenArguments) => Promise<AxiosResponse<ValidateAccessTokenResponse>>;
195
+ constructor(options: ClientOptions);
196
+ /**
197
+ * Get the request configuration.
198
+ * @param resource The resource to fetch. See {@link Resource}.
199
+ * @param options Client options. See {@link ClientOptions}.
200
+ * @param headers Additional headers to include in the request.
201
+ * @returns The request configuration.
202
+ */
203
+ getRequestConfig<T, Protected extends boolean = false>(resource: Resource<T, object, Protected>, options?: Partial<ClientOptions>, headers?: Record<string, string>): {
204
+ headers: {
205
+ Authorization: string;
206
+ 'Content-Type': string;
207
+ 'Battlenet-Namespace'?: string | undefined;
208
+ };
209
+ params: {
210
+ locale: "de_DE" | "en_GB" | "en_US" | "es_ES" | "es_MX" | "fr_FR" | "it_IT" | "ko_KR" | "multi" | "pt_BR" | "pt_PT" | "ru_RU" | "zh_CN" | "zh_TW";
211
+ };
212
+ };
213
+ /**
214
+ * Get the request URL.
215
+ * @param resource The resource to fetch. See {@link Resource}.
216
+ * @param options Client options. See {@link ClientOptions}.
217
+ * @returns The request URL.
218
+ */
219
+ getRequestUrl<T, Protected extends boolean = false>(resource: Resource<T, object, Protected>, options?: Partial<ClientOptions>): string;
220
+ /**
221
+ * Send a request to the Blizzard API.
222
+ * @param resource The resource to fetch. See {@link Resource}.
223
+ * @param options Client options. See {@link ClientOptions}.
224
+ * @param headers Additional headers to include in the request.
225
+ * @returns The response from the Blizzard API. See {@link ResourceResponse}.
226
+ */
227
+ sendRequest<T, Protected extends boolean = false>(resource: Resource<T, object, Protected>, options?: Partial<ClientOptions>, headers?: Record<string, string>): ResourceResponse<AxiosResponse<T>>;
228
228
  }
229
229
 
230
230
  /**
@@ -233,6 +233,6 @@ declare class BlizzardApiClient implements IBlizzardApiClient {
233
233
  * @param onTokenRefresh Callback function to handle token refresh. If set to `true`, the client will automatically refresh the token. If set to `false`, the client will not refresh the token. If set to a function, the function will be called with the new token.
234
234
  * @returns A new Blizzard API client.
235
235
  */
236
- declare const createBlizzardApiClient: (options: ClientOptions, onTokenRefresh?: boolean | ((token: AccessToken) => void)) => Promise<BlizzardApiClient>;
236
+ declare const createBlizzardApiClient: (options: ClientOptions, onTokenRefresh?: ((token: AccessToken) => void) | boolean) => Promise<BlizzardApiClient>;
237
237
 
238
- export { type AccessToken, type AccessTokenRequestArguments, type ClientOptions, type IBlizzardApiClient, type ValidateAccessTokenArguments, type ValidateAccessTokenResponse, createBlizzardApiClient };
238
+ export { type AccessToken, type AccessTokenRequestArguments, type ClientOptions, type IBlizzardApiClient, type ValidateAccessTokenArguments, type ValidateAccessTokenResponse, createBlizzardApiClient, createBlizzardApiClient as default };
package/dist/index.js CHANGED
@@ -1,75 +1,11 @@
1
+ import { stringify } from 'querystring';
2
+ import { getBlizzardApi } from '@blizzard-api/core';
3
+ import axios, { isAxiosError, AxiosError } from 'axios';
4
+
1
5
  // src/client/client.ts
2
- import { stringify } from "querystring";
3
- import { getBlizzardApi } from "@blizzard-api/core";
4
- import axios, { AxiosError, isAxiosError } from "axios";
5
6
  var BlizzardApiClient = class {
6
- defaults;
7
- constructor(options) {
8
- const { origin, locale } = getBlizzardApi(options.origin, options.locale);
9
- this.defaults = {
10
- key: options.key,
11
- secret: options.secret,
12
- token: options.token,
13
- origin,
14
- locale
15
- };
16
- }
17
7
  axios = axios.create();
18
- /**
19
- * Get the request URL.
20
- * @param resource The resource to fetch. See {@link Resource}.
21
- * @param options Client options. See {@link ClientOptions}.
22
- * @returns The request URL.
23
- */
24
- getRequestUrl(resource, options) {
25
- const config = { ...this.defaults, ...options };
26
- const endpoint = getBlizzardApi(config.origin, config.locale);
27
- const backslashSeparator = resource.path.startsWith("/") ? "" : "/";
28
- return `${endpoint.hostname}${backslashSeparator}${resource.path}`;
29
- }
30
- /**
31
- * Get the request configuration.
32
- * @param resource The resource to fetch. See {@link Resource}.
33
- * @param options Client options. See {@link ClientOptions}.
34
- * @param headers Additional headers to include in the request.
35
- * @returns The request configuration.
36
- */
37
- getRequestConfig(resource, options, headers) {
38
- const config = { ...this.defaults, ...options };
39
- const endpoint = getBlizzardApi(config.origin, config.locale);
40
- const namespace = resource.namespace ? { "Battlenet-Namespace": `${resource.namespace}-${endpoint.origin}` } : void 0;
41
- return {
42
- headers: {
43
- ...headers,
44
- ...namespace,
45
- "Content-Type": "application/json",
46
- Authorization: `Bearer ${config.token}`
47
- },
48
- params: {
49
- locale: endpoint.locale,
50
- ...resource.parameters
51
- }
52
- };
53
- }
54
- /**
55
- * Send a request to the Blizzard API.
56
- * @param resource The resource to fetch. See {@link Resource}.
57
- * @param options Client options. See {@link ClientOptions}.
58
- * @param headers Additional headers to include in the request.
59
- * @returns The response from the Blizzard API. See {@link ResourceResponse}.
60
- */
61
- async sendRequest(resource, options, headers) {
62
- const url = this.getRequestUrl(resource, options);
63
- const config = this.getRequestConfig(resource, options, headers);
64
- try {
65
- return await this.axios.get(url, config);
66
- } catch (error) {
67
- if (isAxiosError(error)) {
68
- throw new AxiosError(error.message, error.code);
69
- }
70
- throw error;
71
- }
72
- }
8
+ defaults;
73
9
  /**
74
10
  * Get an access token.
75
11
  * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.
@@ -84,27 +20,20 @@ var BlizzardApiClient = class {
84
20
  * // => 'client-id'
85
21
  */
86
22
  getAccessToken = async (options) => {
87
- const { key, secret, origin } = { ...this.defaults, ...options };
23
+ const { key, origin, secret } = { ...this.defaults, ...options };
88
24
  return this.axios.post(`https://${origin}.battle.net/oauth/token`, void 0, {
89
- params: {
90
- grant_type: "client_credentials"
91
- },
92
25
  auth: {
93
- username: key,
94
- password: secret
26
+ password: secret,
27
+ username: key
95
28
  },
96
29
  headers: {
97
30
  "Content-Type": "application/json"
31
+ },
32
+ params: {
33
+ grant_type: "client_credentials"
98
34
  }
99
35
  });
100
36
  };
101
- /**
102
- * Set the access token.
103
- * @param token The access token.
104
- */
105
- setAccessToken = (token) => {
106
- this.defaults.token = token;
107
- };
108
37
  /**
109
38
  * Refresh the access token.
110
39
  * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.
@@ -123,6 +52,13 @@ var BlizzardApiClient = class {
123
52
  this.setAccessToken(response.data.access_token);
124
53
  return response;
125
54
  };
55
+ /**
56
+ * Set the access token.
57
+ * @param token The access token.
58
+ */
59
+ setAccessToken = (token) => {
60
+ this.defaults.token = token;
61
+ };
126
62
  /**
127
63
  * Validate an access token.
128
64
  * @param options The validate access token arguments. See {@link ValidateAccessTokenArguments}.
@@ -147,6 +83,71 @@ var BlizzardApiClient = class {
147
83
  }
148
84
  );
149
85
  };
86
+ constructor(options) {
87
+ const { locale, origin } = getBlizzardApi(options.origin, options.locale);
88
+ this.defaults = {
89
+ key: options.key,
90
+ locale,
91
+ origin,
92
+ secret: options.secret,
93
+ token: options.token
94
+ };
95
+ }
96
+ /**
97
+ * Get the request configuration.
98
+ * @param resource The resource to fetch. See {@link Resource}.
99
+ * @param options Client options. See {@link ClientOptions}.
100
+ * @param headers Additional headers to include in the request.
101
+ * @returns The request configuration.
102
+ */
103
+ getRequestConfig(resource, options, headers) {
104
+ const config = { ...this.defaults, ...options };
105
+ const endpoint = getBlizzardApi(config.origin, config.locale);
106
+ const namespace = resource.namespace ? { "Battlenet-Namespace": `${resource.namespace}-${endpoint.origin}` } : void 0;
107
+ return {
108
+ headers: {
109
+ ...headers,
110
+ ...namespace,
111
+ Authorization: `Bearer ${config.token}`,
112
+ "Content-Type": "application/json"
113
+ },
114
+ params: {
115
+ locale: endpoint.locale,
116
+ ...resource.parameters
117
+ }
118
+ };
119
+ }
120
+ /**
121
+ * Get the request URL.
122
+ * @param resource The resource to fetch. See {@link Resource}.
123
+ * @param options Client options. See {@link ClientOptions}.
124
+ * @returns The request URL.
125
+ */
126
+ getRequestUrl(resource, options) {
127
+ const config = { ...this.defaults, ...options };
128
+ const endpoint = getBlizzardApi(config.origin, config.locale);
129
+ const backslashSeparator = resource.path.startsWith("/") ? "" : "/";
130
+ return `${endpoint.hostname}${backslashSeparator}${resource.path}`;
131
+ }
132
+ /**
133
+ * Send a request to the Blizzard API.
134
+ * @param resource The resource to fetch. See {@link Resource}.
135
+ * @param options Client options. See {@link ClientOptions}.
136
+ * @param headers Additional headers to include in the request.
137
+ * @returns The response from the Blizzard API. See {@link ResourceResponse}.
138
+ */
139
+ async sendRequest(resource, options, headers) {
140
+ const url = this.getRequestUrl(resource, options);
141
+ const config = this.getRequestConfig(resource, options, headers);
142
+ try {
143
+ return await this.axios.get(url, config);
144
+ } catch (error) {
145
+ if (isAxiosError(error)) {
146
+ throw new AxiosError(error.message, error.code);
147
+ }
148
+ throw error;
149
+ }
150
+ }
150
151
  };
151
152
 
152
153
  // src/client/create-client.ts
@@ -190,7 +191,7 @@ var createBlizzardApiClient = async (options, onTokenRefresh = true) => {
190
191
  }
191
192
  return client;
192
193
  };
193
- export {
194
- createBlizzardApiClient
195
- };
194
+
195
+ export { createBlizzardApiClient, createBlizzardApiClient as default };
196
+ //# sourceMappingURL=out.js.map
196
197
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client/client.ts","../src/client/create-client.ts"],"sourcesContent":["import { stringify } from 'node:querystring';\r\nimport { getBlizzardApi } from '@blizzard-api/core';\r\nimport type { Origins, Locales, ResourceResponse, Resource } from '@blizzard-api/core';\r\nimport type { AxiosResponse } from 'axios';\r\nimport axios, { AxiosError, isAxiosError } from 'axios';\r\nimport type {\r\n AccessToken,\r\n AccessTokenRequestArguments,\r\n ClientOptions,\r\n IBlizzardApiClient,\r\n ValidateAccessTokenArguments,\r\n ValidateAccessTokenResponse,\r\n} from './types';\r\n\r\n/**\r\n * A Blizzard API client.\r\n * @implements IBlizzardApiClient\r\n * @class\r\n * @classdesc A client to interact with the Blizzard API.\r\n * @example\r\n * const client = new BlizzardApiClient({\r\n * key: 'client',\r\n * secret: 'secret',\r\n * origin: 'eu',\r\n * locale: 'en_GB',\r\n * token: 'access'\r\n * });\r\n */\r\nexport class BlizzardApiClient implements IBlizzardApiClient {\r\n public defaults: {\r\n key: string;\r\n secret: string;\r\n origin: Origins;\r\n locale: Locales;\r\n token?: string;\r\n };\r\n\r\n constructor(options: ClientOptions) {\r\n const { origin, locale } = getBlizzardApi(options.origin, options.locale);\r\n this.defaults = {\r\n key: options.key,\r\n secret: options.secret,\r\n token: options.token,\r\n origin: origin,\r\n locale: locale,\r\n };\r\n }\r\n\r\n private axios = axios.create();\r\n\r\n /**\r\n * Get the request URL.\r\n * @param resource The resource to fetch. See {@link Resource}.\r\n * @param options Client options. See {@link ClientOptions}.\r\n * @returns The request URL.\r\n */\r\n public getRequestUrl<T, Protected extends boolean = false>(\r\n resource: Resource<T, object, Protected>,\r\n options?: Partial<ClientOptions>,\r\n ) {\r\n const config = { ...this.defaults, ...options };\r\n const endpoint = getBlizzardApi(config.origin, config.locale);\r\n\r\n const backslashSeparator = resource.path.startsWith('/') ? '' : '/';\r\n\r\n return `${endpoint.hostname}${backslashSeparator}${resource.path}`;\r\n }\r\n\r\n /**\r\n * Get the request configuration.\r\n * @param resource The resource to fetch. See {@link Resource}.\r\n * @param options Client options. See {@link ClientOptions}.\r\n * @param headers Additional headers to include in the request.\r\n * @returns The request configuration.\r\n */\r\n public getRequestConfig<T, Protected extends boolean = false>(\r\n resource: Resource<T, object, Protected>,\r\n options?: Partial<ClientOptions>,\r\n headers?: Record<string, string>,\r\n ) {\r\n const config = { ...this.defaults, ...options };\r\n const endpoint = getBlizzardApi(config.origin, config.locale);\r\n\r\n const namespace = resource.namespace\r\n ? { 'Battlenet-Namespace': `${resource.namespace}-${endpoint.origin}` }\r\n : undefined;\r\n\r\n return {\r\n headers: {\r\n ...headers,\r\n ...namespace,\r\n 'Content-Type': 'application/json',\r\n Authorization: `Bearer ${config.token}`,\r\n },\r\n params: {\r\n locale: endpoint.locale,\r\n ...resource.parameters,\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Send a request to the Blizzard API.\r\n * @param resource The resource to fetch. See {@link Resource}.\r\n * @param options Client options. See {@link ClientOptions}.\r\n * @param headers Additional headers to include in the request.\r\n * @returns The response from the Blizzard API. See {@link ResourceResponse}.\r\n */\r\n public async sendRequest<T, Protected extends boolean = false>(\r\n resource: Resource<T, object, Protected>,\r\n options?: Partial<ClientOptions>,\r\n headers?: Record<string, string>,\r\n ): ResourceResponse<AxiosResponse<T>> {\r\n const url = this.getRequestUrl(resource, options);\r\n const config = this.getRequestConfig(resource, options, headers);\r\n\r\n try {\r\n return await this.axios.get<T>(url, config);\r\n } catch (error) {\r\n if (isAxiosError(error)) {\r\n throw new AxiosError(error.message, error.code);\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Get an access token.\r\n * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.\r\n * @returns The access token. See {@link AccessToken}.\r\n * @example\r\n * const response = await client.getAccessToken();\r\n * const { access_token, token_type, expires_in, sub } = response.data;\r\n * console.log(access_token, token_type, expires_in, sub);\r\n * // => 'access'\r\n * // => 'bearer'\r\n * // => 86399\r\n * // => 'client-id'\r\n */\r\n public getAccessToken = async (options?: AccessTokenRequestArguments): Promise<AxiosResponse<AccessToken>> => {\r\n const { key, secret, origin } = { ...this.defaults, ...options };\r\n return this.axios.post<AccessToken>(`https://${origin}.battle.net/oauth/token`, undefined, {\r\n params: {\r\n grant_type: 'client_credentials',\r\n },\r\n auth: {\r\n username: key,\r\n password: secret,\r\n },\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n });\r\n };\r\n\r\n /**\r\n * Set the access token.\r\n * @param token The access token.\r\n */\r\n public setAccessToken = (token: string): void => {\r\n this.defaults.token = token;\r\n };\r\n\r\n /**\r\n * Refresh the access token.\r\n * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.\r\n * @returns The access token. See {@link AccessToken}.\r\n * @example\r\n * const response = await client.refreshAccessToken();\r\n * const { access_token, token_type, expires_in, sub } = response.data;\r\n * console.log(access_token, token_type, expires_in, sub);\r\n * // => 'access'\r\n * // => 'bearer'\r\n * // => 86399\r\n * // => 'client-id'\r\n */\r\n public refreshAccessToken = async (options?: AccessTokenRequestArguments): Promise<AxiosResponse<AccessToken>> => {\r\n const response = await this.getAccessToken(options);\r\n this.setAccessToken(response.data.access_token);\r\n return response;\r\n };\r\n\r\n /**\r\n * Validate an access token.\r\n * @param options The validate access token arguments. See {@link ValidateAccessTokenArguments}.\r\n * @returns The response from the Blizzard API. See {@link ValidateAccessTokenResponse}.\r\n * @example\r\n * const response = await client.validateAccessToken({ token: 'access' });\r\n * console.log(response.data.client_id);\r\n * // => 'client-id'\r\n */\r\n public validateAccessToken = async (\r\n options?: ValidateAccessTokenArguments,\r\n ): Promise<AxiosResponse<ValidateAccessTokenResponse>> => {\r\n const { origin, token } = { ...this.defaults, ...options };\r\n\r\n if (!token) {\r\n throw new Error('No token has been set previously or been passed to the validateAccessToken method.');\r\n }\r\n\r\n return await this.axios.post<ValidateAccessTokenResponse>(\r\n `https://${origin}.battle.net/oauth/check_token`,\r\n stringify({ token }),\r\n {\r\n headers: {\r\n 'Content-Type': 'application/x-www-form-urlencoded',\r\n },\r\n },\r\n );\r\n };\r\n}\r\n","import { BlizzardApiClient } from './client';\r\nimport type { AccessToken, ClientOptions } from './types';\r\n\r\nconst getTokenExpiration = (expiresIn: number) => expiresIn * 1000 - 60_000;\r\n\r\n/**\r\n * Create a new Blizzard API client.\r\n * @param options Client options, see {@link ClientOptions} & https://develop.battle.net/documentation/guides/getting-started\r\n * @param onTokenRefresh Callback function to handle token refresh. If set to `true`, the client will automatically refresh the token. If set to `false`, the client will not refresh the token. If set to a function, the function will be called with the new token.\r\n * @returns A new Blizzard API client.\r\n */\r\nexport const createBlizzardApiClient = async (\r\n options: ClientOptions,\r\n onTokenRefresh: boolean | ((token: AccessToken) => void) = true,\r\n): Promise<BlizzardApiClient> => {\r\n const { key, secret, token } = options;\r\n if (!key) {\r\n throw new Error(`Client missing 'key' parameter`);\r\n }\r\n if (!secret) {\r\n throw new Error(`Client missing 'secret' parameter`);\r\n }\r\n\r\n const client = new BlizzardApiClient(options);\r\n\r\n const refreshToken = async () => {\r\n const response = await client.getAccessToken();\r\n\r\n client.setAccessToken(response.data.access_token);\r\n\r\n if (typeof onTokenRefresh === 'function') {\r\n onTokenRefresh?.(response.data);\r\n }\r\n\r\n //Schedule a refresh of the token\r\n const timeout = setTimeout(() => void refreshToken(), getTokenExpiration(response.data.expires_in));\r\n timeout.unref();\r\n };\r\n\r\n //If tokenRefresh is false, return the client without refreshing the token\r\n if (!onTokenRefresh) {\r\n return client;\r\n }\r\n\r\n if (token) {\r\n try {\r\n //If token is set, validate the token\r\n const validatedToken = await client.validateAccessToken({ token });\r\n const expiry = getTokenExpiration(validatedToken.data.exp);\r\n //If token is expiring in less than 60 seconds, refresh the token\r\n if (expiry - Date.now() < 60_000) {\r\n await refreshToken();\r\n } else {\r\n //If token is not expiring, schedule a refresh\r\n const timeout = setTimeout(() => void refreshToken(), expiry - Date.now());\r\n //Unref the timeout so the process can exit\r\n timeout.unref();\r\n }\r\n } catch {\r\n //If token is invalid, refresh the token\r\n await refreshToken();\r\n }\r\n } else {\r\n //If token is not set, refresh the token\r\n await refreshToken();\r\n }\r\n\r\n return client;\r\n};\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/client/client.ts","../src/client/create-client.ts"],"names":[],"mappings":";AAAA,SAAS,iBAAiB;AAC1B,SAAS,sBAAsB;AAG/B,OAAO,SAAS,YAAY,oBAAoB;AAwBzC,IAAM,oBAAN,MAAsD;AAAA,EACnD,QAAQ,MAAM,OAAO;AAAA,EAEtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBA,iBAAiB,OAAO,YAA+E;AAC5G,UAAM,EAAE,KAAK,QAAQ,OAAO,IAAI,EAAE,GAAG,KAAK,UAAU,GAAG,QAAQ;AAC/D,WAAO,KAAK,MAAM,KAAkB,WAAW,MAAM,2BAA2B,QAAW;AAAA,MACzF,MAAM;AAAA,QACJ,UAAU;AAAA,QACV,UAAU;AAAA,MACZ;AAAA,MACA,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,QAAQ;AAAA,QACN,YAAY;AAAA,MACd;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeO,qBAAqB,OAAO,YAA+E;AAChH,UAAM,WAAW,MAAM,KAAK,eAAe,OAAO;AAClD,SAAK,eAAe,SAAS,KAAK,YAAY;AAC9C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,iBAAiB,CAAC,UAAwB;AAC/C,SAAK,SAAS,QAAQ;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWO,sBAAsB,OAC3B,YACwD;AACxD,UAAM,EAAE,QAAQ,MAAM,IAAI,EAAE,GAAG,KAAK,UAAU,GAAG,QAAQ;AAEzD,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,oFAAoF;AAAA,IACtG;AAEA,WAAO,MAAM,KAAK,MAAM;AAAA,MACtB,WAAW,MAAM;AAAA,MACjB,UAAU,EAAE,MAAM,CAAC;AAAA,MACnB;AAAA,QACE,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YAAY,SAAwB;AAClC,UAAM,EAAE,QAAQ,OAAO,IAAI,eAAe,QAAQ,QAAQ,QAAQ,MAAM;AACxE,SAAK,WAAW;AAAA,MACd,KAAK,QAAQ;AAAA,MACb;AAAA,MACA;AAAA,MACA,QAAQ,QAAQ;AAAA,MAChB,OAAO,QAAQ;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,iBACL,UACA,SACA,SACA;AACA,UAAM,SAAS,EAAE,GAAG,KAAK,UAAU,GAAG,QAAQ;AAC9C,UAAM,WAAW,eAAe,OAAO,QAAQ,OAAO,MAAM;AAE5D,UAAM,YAAY,SAAS,YACvB,EAAE,uBAAuB,GAAG,SAAS,SAAS,IAAI,SAAS,MAAM,GAAG,IACpE;AAEJ,WAAO;AAAA,MACL,SAAS;AAAA,QACP,GAAG;AAAA,QACH,GAAG;AAAA,QACH,eAAe,UAAU,OAAO,KAAK;AAAA,QACrC,gBAAgB;AAAA,MAClB;AAAA,MACA,QAAQ;AAAA,QACN,QAAQ,SAAS;AAAA,QACjB,GAAG,SAAS;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,cACL,UACA,SACA;AACA,UAAM,SAAS,EAAE,GAAG,KAAK,UAAU,GAAG,QAAQ;AAC9C,UAAM,WAAW,eAAe,OAAO,QAAQ,OAAO,MAAM;AAE5D,UAAM,qBAAqB,SAAS,KAAK,WAAW,GAAG,IAAI,KAAK;AAEhE,WAAO,GAAG,SAAS,QAAQ,GAAG,kBAAkB,GAAG,SAAS,IAAI;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,YACX,UACA,SACA,SACoC;AACpC,UAAM,MAAM,KAAK,cAAc,UAAU,OAAO;AAChD,UAAM,SAAS,KAAK,iBAAiB,UAAU,SAAS,OAAO;AAE/D,QAAI;AACF,aAAO,MAAM,KAAK,MAAM,IAAO,KAAK,MAAM;AAAA,IAC5C,SAAS,OAAO;AACd,UAAI,aAAa,KAAK,GAAG;AACvB,cAAM,IAAI,WAAW,MAAM,SAAS,MAAM,IAAI;AAAA,MAChD;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACF;;;AC/MA,IAAM,qBAAqB,CAAC,cAAsB,YAAY,MAAO;AAQ9D,IAAM,0BAA0B,OACrC,SACA,iBAA2D,SAC5B;AAC/B,QAAM,EAAE,KAAK,QAAQ,MAAM,IAAI;AAC/B,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,MAAM,gCAAgC;AAAA,EAClD;AACA,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AAEA,QAAM,SAAS,IAAI,kBAAkB,OAAO;AAE5C,QAAM,eAAe,YAAY;AAC/B,UAAM,WAAW,MAAM,OAAO,eAAe;AAE7C,WAAO,eAAe,SAAS,KAAK,YAAY;AAEhD,QAAI,OAAO,mBAAmB,YAAY;AACxC,uBAAiB,SAAS,IAAI;AAAA,IAChC;AAGA,UAAM,UAAU,WAAW,MAAM,KAAK,aAAa,GAAG,mBAAmB,SAAS,KAAK,UAAU,CAAC;AAClG,YAAQ,MAAM;AAAA,EAChB;AAGA,MAAI,CAAC,gBAAgB;AACnB,WAAO;AAAA,EACT;AAEA,MAAI,OAAO;AACT,QAAI;AAEF,YAAM,iBAAiB,MAAM,OAAO,oBAAoB,EAAE,MAAM,CAAC;AACjE,YAAM,SAAS,mBAAmB,eAAe,KAAK,GAAG;AAEzD,UAAI,SAAS,KAAK,IAAI,IAAI,KAAQ;AAChC,cAAM,aAAa;AAAA,MACrB,OAAO;AAEL,cAAM,UAAU,WAAW,MAAM,KAAK,aAAa,GAAG,SAAS,KAAK,IAAI,CAAC;AAEzE,gBAAQ,MAAM;AAAA,MAChB;AAAA,IACF,QAAQ;AAEN,YAAM,aAAa;AAAA,IACrB;AAAA,EACF,OAAO;AAEL,UAAM,aAAa;AAAA,EACrB;AAEA,SAAO;AACT","sourcesContent":["import { stringify } from 'node:querystring';\r\nimport { getBlizzardApi } from '@blizzard-api/core';\r\nimport type { Locales, Origins, Resource, ResourceResponse } from '@blizzard-api/core';\r\nimport type { AxiosResponse } from 'axios';\r\nimport axios, { AxiosError, isAxiosError } from 'axios';\r\nimport type {\r\n AccessToken,\r\n AccessTokenRequestArguments,\r\n ClientOptions,\r\n IBlizzardApiClient,\r\n ValidateAccessTokenArguments,\r\n ValidateAccessTokenResponse,\r\n} from './types';\r\n\r\n/**\r\n * A Blizzard API client.\r\n * @implements IBlizzardApiClient\r\n * @class\r\n * @classdesc A client to interact with the Blizzard API.\r\n * @example\r\n * const client = new BlizzardApiClient({\r\n * key: 'client',\r\n * secret: 'secret',\r\n * origin: 'eu',\r\n * locale: 'en_GB',\r\n * token: 'access'\r\n * });\r\n */\r\nexport class BlizzardApiClient implements IBlizzardApiClient {\r\n private axios = axios.create();\r\n\r\n public defaults: {\r\n key: string;\r\n locale: Locales;\r\n origin: Origins;\r\n secret: string;\r\n token?: string;\r\n };\r\n\r\n /**\r\n * Get an access token.\r\n * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.\r\n * @returns The access token. See {@link AccessToken}.\r\n * @example\r\n * const response = await client.getAccessToken();\r\n * const { access_token, token_type, expires_in, sub } = response.data;\r\n * console.log(access_token, token_type, expires_in, sub);\r\n * // => 'access'\r\n * // => 'bearer'\r\n * // => 86399\r\n * // => 'client-id'\r\n */\r\n public getAccessToken = async (options?: AccessTokenRequestArguments): Promise<AxiosResponse<AccessToken>> => {\r\n const { key, origin, secret } = { ...this.defaults, ...options };\r\n return this.axios.post<AccessToken>(`https://${origin}.battle.net/oauth/token`, undefined, {\r\n auth: {\r\n password: secret,\r\n username: key,\r\n },\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n params: {\r\n grant_type: 'client_credentials',\r\n },\r\n });\r\n };\r\n\r\n /**\r\n * Refresh the access token.\r\n * @param options The access token request arguments. See {@link AccessTokenRequestArguments}.\r\n * @returns The access token. See {@link AccessToken}.\r\n * @example\r\n * const response = await client.refreshAccessToken();\r\n * const { access_token, token_type, expires_in, sub } = response.data;\r\n * console.log(access_token, token_type, expires_in, sub);\r\n * // => 'access'\r\n * // => 'bearer'\r\n * // => 86399\r\n * // => 'client-id'\r\n */\r\n public refreshAccessToken = async (options?: AccessTokenRequestArguments): Promise<AxiosResponse<AccessToken>> => {\r\n const response = await this.getAccessToken(options);\r\n this.setAccessToken(response.data.access_token);\r\n return response;\r\n };\r\n\r\n /**\r\n * Set the access token.\r\n * @param token The access token.\r\n */\r\n public setAccessToken = (token: string): void => {\r\n this.defaults.token = token;\r\n };\r\n\r\n /**\r\n * Validate an access token.\r\n * @param options The validate access token arguments. See {@link ValidateAccessTokenArguments}.\r\n * @returns The response from the Blizzard API. See {@link ValidateAccessTokenResponse}.\r\n * @example\r\n * const response = await client.validateAccessToken({ token: 'access' });\r\n * console.log(response.data.client_id);\r\n * // => 'client-id'\r\n */\r\n public validateAccessToken = async (\r\n options?: ValidateAccessTokenArguments,\r\n ): Promise<AxiosResponse<ValidateAccessTokenResponse>> => {\r\n const { origin, token } = { ...this.defaults, ...options };\r\n\r\n if (!token) {\r\n throw new Error('No token has been set previously or been passed to the validateAccessToken method.');\r\n }\r\n\r\n return await this.axios.post<ValidateAccessTokenResponse>(\r\n `https://${origin}.battle.net/oauth/check_token`,\r\n stringify({ token }),\r\n {\r\n headers: {\r\n 'Content-Type': 'application/x-www-form-urlencoded',\r\n },\r\n },\r\n );\r\n };\r\n\r\n constructor(options: ClientOptions) {\r\n const { locale, origin } = getBlizzardApi(options.origin, options.locale);\r\n this.defaults = {\r\n key: options.key,\r\n locale: locale,\r\n origin: origin,\r\n secret: options.secret,\r\n token: options.token,\r\n };\r\n }\r\n\r\n /**\r\n * Get the request configuration.\r\n * @param resource The resource to fetch. See {@link Resource}.\r\n * @param options Client options. See {@link ClientOptions}.\r\n * @param headers Additional headers to include in the request.\r\n * @returns The request configuration.\r\n */\r\n public getRequestConfig<T, Protected extends boolean = false>(\r\n resource: Resource<T, object, Protected>,\r\n options?: Partial<ClientOptions>,\r\n headers?: Record<string, string>,\r\n ) {\r\n const config = { ...this.defaults, ...options };\r\n const endpoint = getBlizzardApi(config.origin, config.locale);\r\n\r\n const namespace = resource.namespace\r\n ? { 'Battlenet-Namespace': `${resource.namespace}-${endpoint.origin}` }\r\n : undefined;\r\n\r\n return {\r\n headers: {\r\n ...headers,\r\n ...namespace,\r\n Authorization: `Bearer ${config.token}`,\r\n 'Content-Type': 'application/json',\r\n },\r\n params: {\r\n locale: endpoint.locale,\r\n ...resource.parameters,\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Get the request URL.\r\n * @param resource The resource to fetch. See {@link Resource}.\r\n * @param options Client options. See {@link ClientOptions}.\r\n * @returns The request URL.\r\n */\r\n public getRequestUrl<T, Protected extends boolean = false>(\r\n resource: Resource<T, object, Protected>,\r\n options?: Partial<ClientOptions>,\r\n ) {\r\n const config = { ...this.defaults, ...options };\r\n const endpoint = getBlizzardApi(config.origin, config.locale);\r\n\r\n const backslashSeparator = resource.path.startsWith('/') ? '' : '/';\r\n\r\n return `${endpoint.hostname}${backslashSeparator}${resource.path}`;\r\n }\r\n\r\n /**\r\n * Send a request to the Blizzard API.\r\n * @param resource The resource to fetch. See {@link Resource}.\r\n * @param options Client options. See {@link ClientOptions}.\r\n * @param headers Additional headers to include in the request.\r\n * @returns The response from the Blizzard API. See {@link ResourceResponse}.\r\n */\r\n public async sendRequest<T, Protected extends boolean = false>(\r\n resource: Resource<T, object, Protected>,\r\n options?: Partial<ClientOptions>,\r\n headers?: Record<string, string>,\r\n ): ResourceResponse<AxiosResponse<T>> {\r\n const url = this.getRequestUrl(resource, options);\r\n const config = this.getRequestConfig(resource, options, headers);\r\n\r\n try {\r\n return await this.axios.get<T>(url, config);\r\n } catch (error) {\r\n if (isAxiosError(error)) {\r\n throw new AxiosError(error.message, error.code);\r\n }\r\n throw error;\r\n }\r\n }\r\n}\r\n","import { BlizzardApiClient } from './client';\r\nimport type { AccessToken, ClientOptions } from './types';\r\n\r\nconst getTokenExpiration = (expiresIn: number) => expiresIn * 1000 - 60_000;\r\n\r\n/**\r\n * Create a new Blizzard API client.\r\n * @param options Client options, see {@link ClientOptions} & https://develop.battle.net/documentation/guides/getting-started\r\n * @param onTokenRefresh Callback function to handle token refresh. If set to `true`, the client will automatically refresh the token. If set to `false`, the client will not refresh the token. If set to a function, the function will be called with the new token.\r\n * @returns A new Blizzard API client.\r\n */\r\nexport const createBlizzardApiClient = async (\r\n options: ClientOptions,\r\n onTokenRefresh: ((token: AccessToken) => void) | boolean = true,\r\n): Promise<BlizzardApiClient> => {\r\n const { key, secret, token } = options;\r\n if (!key) {\r\n throw new Error(`Client missing 'key' parameter`);\r\n }\r\n if (!secret) {\r\n throw new Error(`Client missing 'secret' parameter`);\r\n }\r\n\r\n const client = new BlizzardApiClient(options);\r\n\r\n const refreshToken = async () => {\r\n const response = await client.getAccessToken();\r\n\r\n client.setAccessToken(response.data.access_token);\r\n\r\n if (typeof onTokenRefresh === 'function') {\r\n onTokenRefresh?.(response.data);\r\n }\r\n\r\n //Schedule a refresh of the token\r\n const timeout = setTimeout(() => void refreshToken(), getTokenExpiration(response.data.expires_in));\r\n timeout.unref();\r\n };\r\n\r\n //If tokenRefresh is false, return the client without refreshing the token\r\n if (!onTokenRefresh) {\r\n return client;\r\n }\r\n\r\n if (token) {\r\n try {\r\n //If token is set, validate the token\r\n const validatedToken = await client.validateAccessToken({ token });\r\n const expiry = getTokenExpiration(validatedToken.data.exp);\r\n //If token is expiring in less than 60 seconds, refresh the token\r\n if (expiry - Date.now() < 60_000) {\r\n await refreshToken();\r\n } else {\r\n //If token is not expiring, schedule a refresh\r\n const timeout = setTimeout(() => void refreshToken(), expiry - Date.now());\r\n //Unref the timeout so the process can exit\r\n timeout.unref();\r\n }\r\n } catch {\r\n //If token is invalid, refresh the token\r\n await refreshToken();\r\n }\r\n } else {\r\n //If token is not set, refresh the token\r\n await refreshToken();\r\n }\r\n\r\n return client;\r\n};\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blizzard-api/client",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "license": "MIT",
5
5
  "author": "Putro",
6
6
  "description": "A node.js axios client to integrate with the blizzard battle.net api.",
@@ -9,7 +9,9 @@
9
9
  "engines": {
10
10
  "node": "^18.18 || ^20.9 || ^21.1 || ^22"
11
11
  },
12
- "main": "./dist/index.js",
12
+ "main": "./dist/index.cjs",
13
+ "module": "./dist/index.js",
14
+ "types": "./dist/index.d.ts",
13
15
  "exports": {
14
16
  "import": {
15
17
  "types": "./dist/index.d.ts",
@@ -45,13 +47,13 @@
45
47
  "axios": "1.7.2"
46
48
  },
47
49
  "peerDependencies": {
48
- "@blizzard-api/core": "1.1.0"
50
+ "@blizzard-api/core": "1.1.1"
49
51
  },
50
52
  "devDependencies": {
51
- "@blizzard-api/classic-wow": "1.1.1",
52
- "@blizzard-api/core": "1.1.0",
53
- "@blizzard-api/d3": "0.1.0",
54
- "@blizzard-api/wow": "1.1.1"
53
+ "@blizzard-api/classic-wow": "1.1.3",
54
+ "@blizzard-api/core": "1.1.1",
55
+ "@blizzard-api/d3": "0.1.2",
56
+ "@blizzard-api/wow": "1.1.3"
55
57
  },
56
58
  "scripts": {
57
59
  "build": "tsup",