@blizzard-api/client 1.0.1 → 1.0.3
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 +1 -1
- package/dist/index.cjs +91 -121
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -50
- package/dist/index.d.ts +50 -50
- package/dist/index.js +86 -85
- package/dist/index.js.map +1 -1
- package/package.json +10 -7
package/README.md
CHANGED
|
@@ -4,12 +4,12 @@ This package provides a client that is meant to be used together with one or mor
|
|
|
4
4
|
|
|
5
5
|
Currently available packages are:
|
|
6
6
|
|
|
7
|
+
- `@blizzard-api/d3`
|
|
7
8
|
- `@blizzard-api/wow`
|
|
8
9
|
- `@blizzard-api/classic-wow`
|
|
9
10
|
|
|
10
11
|
Planned packages are:
|
|
11
12
|
|
|
12
|
-
- `@blizzard-api/d3`
|
|
13
13
|
- `@blizzard-api/hs`
|
|
14
14
|
- `@blizzard-api/sc2`
|
|
15
15
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,111 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
|
|
7
|
-
|
|
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
|
+
var querystring = require('querystring');
|
|
4
|
+
var core = require('@blizzard-api/core');
|
|
5
|
+
var axios = require('axios');
|
|
6
|
+
|
|
7
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
29
8
|
|
|
30
|
-
|
|
31
|
-
var src_exports = {};
|
|
32
|
-
__export(src_exports, {
|
|
33
|
-
createBlizzardApiClient: () => createBlizzardApiClient
|
|
34
|
-
});
|
|
35
|
-
module.exports = __toCommonJS(src_exports);
|
|
9
|
+
var axios__default = /*#__PURE__*/_interopDefault(axios);
|
|
36
10
|
|
|
37
11
|
// 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
12
|
var BlizzardApiClient = class {
|
|
13
|
+
axios = axios__default.default.create();
|
|
42
14
|
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
15
|
/**
|
|
110
16
|
* Get an access token.
|
|
111
17
|
* @param options The access token request arguments. See {@link AccessTokenRequestArguments}.
|
|
@@ -120,27 +26,20 @@ var BlizzardApiClient = class {
|
|
|
120
26
|
* // => 'client-id'
|
|
121
27
|
*/
|
|
122
28
|
getAccessToken = async (options) => {
|
|
123
|
-
const { key,
|
|
29
|
+
const { key, origin, secret } = { ...this.defaults, ...options };
|
|
124
30
|
return this.axios.post(`https://${origin}.battle.net/oauth/token`, void 0, {
|
|
125
|
-
params: {
|
|
126
|
-
grant_type: "client_credentials"
|
|
127
|
-
},
|
|
128
31
|
auth: {
|
|
129
|
-
|
|
130
|
-
|
|
32
|
+
password: secret,
|
|
33
|
+
username: key
|
|
131
34
|
},
|
|
132
35
|
headers: {
|
|
133
36
|
"Content-Type": "application/json"
|
|
37
|
+
},
|
|
38
|
+
params: {
|
|
39
|
+
grant_type: "client_credentials"
|
|
134
40
|
}
|
|
135
41
|
});
|
|
136
42
|
};
|
|
137
|
-
/**
|
|
138
|
-
* Set the access token.
|
|
139
|
-
* @param token The access token.
|
|
140
|
-
*/
|
|
141
|
-
setAccessToken = (token) => {
|
|
142
|
-
this.defaults.token = token;
|
|
143
|
-
};
|
|
144
43
|
/**
|
|
145
44
|
* Refresh the access token.
|
|
146
45
|
* @param options The access token request arguments. See {@link AccessTokenRequestArguments}.
|
|
@@ -159,6 +58,13 @@ var BlizzardApiClient = class {
|
|
|
159
58
|
this.setAccessToken(response.data.access_token);
|
|
160
59
|
return response;
|
|
161
60
|
};
|
|
61
|
+
/**
|
|
62
|
+
* Set the access token.
|
|
63
|
+
* @param token The access token.
|
|
64
|
+
*/
|
|
65
|
+
setAccessToken = (token) => {
|
|
66
|
+
this.defaults.token = token;
|
|
67
|
+
};
|
|
162
68
|
/**
|
|
163
69
|
* Validate an access token.
|
|
164
70
|
* @param options The validate access token arguments. See {@link ValidateAccessTokenArguments}.
|
|
@@ -175,7 +81,7 @@ var BlizzardApiClient = class {
|
|
|
175
81
|
}
|
|
176
82
|
return await this.axios.post(
|
|
177
83
|
`https://${origin}.battle.net/oauth/check_token`,
|
|
178
|
-
|
|
84
|
+
querystring.stringify({ token }),
|
|
179
85
|
{
|
|
180
86
|
headers: {
|
|
181
87
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
@@ -183,6 +89,71 @@ var BlizzardApiClient = class {
|
|
|
183
89
|
}
|
|
184
90
|
);
|
|
185
91
|
};
|
|
92
|
+
constructor(options) {
|
|
93
|
+
const { locale, origin } = core.getBlizzardApi(options.origin, options.locale);
|
|
94
|
+
this.defaults = {
|
|
95
|
+
key: options.key,
|
|
96
|
+
locale,
|
|
97
|
+
origin,
|
|
98
|
+
secret: options.secret,
|
|
99
|
+
token: options.token
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get the request configuration.
|
|
104
|
+
* @param resource The resource to fetch. See {@link Resource}.
|
|
105
|
+
* @param options Client options. See {@link ClientOptions}.
|
|
106
|
+
* @param headers Additional headers to include in the request.
|
|
107
|
+
* @returns The request configuration.
|
|
108
|
+
*/
|
|
109
|
+
getRequestConfig(resource, options, headers) {
|
|
110
|
+
const config = { ...this.defaults, ...options };
|
|
111
|
+
const endpoint = core.getBlizzardApi(config.origin, config.locale);
|
|
112
|
+
const namespace = resource.namespace ? { "Battlenet-Namespace": `${resource.namespace}-${endpoint.origin}` } : void 0;
|
|
113
|
+
return {
|
|
114
|
+
headers: {
|
|
115
|
+
...headers,
|
|
116
|
+
...namespace,
|
|
117
|
+
Authorization: `Bearer ${config.token}`,
|
|
118
|
+
"Content-Type": "application/json"
|
|
119
|
+
},
|
|
120
|
+
params: {
|
|
121
|
+
locale: endpoint.locale,
|
|
122
|
+
...resource.parameters
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Get the request URL.
|
|
128
|
+
* @param resource The resource to fetch. See {@link Resource}.
|
|
129
|
+
* @param options Client options. See {@link ClientOptions}.
|
|
130
|
+
* @returns The request URL.
|
|
131
|
+
*/
|
|
132
|
+
getRequestUrl(resource, options) {
|
|
133
|
+
const config = { ...this.defaults, ...options };
|
|
134
|
+
const endpoint = core.getBlizzardApi(config.origin, config.locale);
|
|
135
|
+
const backslashSeparator = resource.path.startsWith("/") ? "" : "/";
|
|
136
|
+
return `${endpoint.hostname}${backslashSeparator}${resource.path}`;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Send a request to the Blizzard API.
|
|
140
|
+
* @param resource The resource to fetch. See {@link Resource}.
|
|
141
|
+
* @param options Client options. See {@link ClientOptions}.
|
|
142
|
+
* @param headers Additional headers to include in the request.
|
|
143
|
+
* @returns The response from the Blizzard API. See {@link ResourceResponse}.
|
|
144
|
+
*/
|
|
145
|
+
async sendRequest(resource, options, headers) {
|
|
146
|
+
const url = this.getRequestUrl(resource, options);
|
|
147
|
+
const config = this.getRequestConfig(resource, options, headers);
|
|
148
|
+
try {
|
|
149
|
+
return await this.axios.get(url, config);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
if (axios.isAxiosError(error)) {
|
|
152
|
+
throw new axios.AxiosError(error.message, error.code);
|
|
153
|
+
}
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
186
157
|
};
|
|
187
158
|
|
|
188
159
|
// src/client/create-client.ts
|
|
@@ -226,8 +197,7 @@ var createBlizzardApiClient = async (options, onTokenRefresh = true) => {
|
|
|
226
197
|
}
|
|
227
198
|
return client;
|
|
228
199
|
};
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
});
|
|
200
|
+
|
|
201
|
+
exports.createBlizzardApiClient = createBlizzardApiClient;
|
|
202
|
+
//# sourceMappingURL=out.js.map
|
|
233
203
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -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?:
|
|
236
|
+
declare const createBlizzardApiClient: (options: ClientOptions, onTokenRefresh?: ((token: AccessToken) => void) | boolean) => Promise<BlizzardApiClient>;
|
|
237
237
|
|
|
238
238
|
export { type AccessToken, type AccessTokenRequestArguments, type ClientOptions, type IBlizzardApiClient, type ValidateAccessTokenArguments, type ValidateAccessTokenResponse, createBlizzardApiClient };
|
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?:
|
|
236
|
+
declare const createBlizzardApiClient: (options: ClientOptions, onTokenRefresh?: ((token: AccessToken) => void) | boolean) => Promise<BlizzardApiClient>;
|
|
237
237
|
|
|
238
238
|
export { type AccessToken, type AccessTokenRequestArguments, type ClientOptions, type IBlizzardApiClient, type ValidateAccessTokenArguments, type ValidateAccessTokenResponse, createBlizzardApiClient };
|
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,
|
|
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
|
-
|
|
94
|
-
|
|
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
|
-
|
|
194
|
-
|
|
195
|
-
|
|
194
|
+
|
|
195
|
+
export { createBlizzardApiClient };
|
|
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":"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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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blizzard-api/client",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
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.
|
|
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",
|
|
@@ -42,15 +44,16 @@
|
|
|
42
44
|
"hearthstone"
|
|
43
45
|
],
|
|
44
46
|
"dependencies": {
|
|
45
|
-
"axios": "1.
|
|
47
|
+
"axios": "1.7.2"
|
|
46
48
|
},
|
|
47
49
|
"peerDependencies": {
|
|
48
|
-
"@blizzard-api/core": "1.1.
|
|
50
|
+
"@blizzard-api/core": "1.1.1"
|
|
49
51
|
},
|
|
50
52
|
"devDependencies": {
|
|
51
|
-
"@blizzard-api/classic-wow": "1.1.
|
|
52
|
-
"@blizzard-api/core": "1.1.
|
|
53
|
-
"@blizzard-api/
|
|
53
|
+
"@blizzard-api/classic-wow": "1.1.2",
|
|
54
|
+
"@blizzard-api/core": "1.1.1",
|
|
55
|
+
"@blizzard-api/d3": "0.1.1",
|
|
56
|
+
"@blizzard-api/wow": "1.1.2"
|
|
54
57
|
},
|
|
55
58
|
"scripts": {
|
|
56
59
|
"build": "tsup",
|