@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 +2 -0
- package/dist/index.cjs +94 -121
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -51
- package/dist/index.d.ts +51 -51
- package/dist/index.js +86 -85
- package/dist/index.js.map +1 -1
- package/package.json +9 -7
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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,
|
|
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
|
-
|
|
130
|
-
|
|
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
|
-
|
|
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
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
202
|
+
|
|
203
|
+
exports.createBlizzardApiClient = createBlizzardApiClient;
|
|
204
|
+
exports.default = createBlizzardApiClient;
|
|
205
|
+
//# sourceMappingURL=out.js.map
|
|
233
206
|
//# 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
|
-
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?:
|
|
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,
|
|
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, 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":"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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.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.
|
|
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.
|
|
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/d3": "0.1.
|
|
54
|
-
"@blizzard-api/wow": "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",
|