dupr-js-client 0.1.0 → 0.1.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/package.json +7 -5
- package/dist/index.cjs +0 -603
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -516
package/package.json
CHANGED
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dupr-js-client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "A comprehensive TypeScript/JavaScript client for the DUPR (Dynamic Universal Pickleball Rating) API.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Sunny Tambi",
|
|
7
7
|
"type": "module",
|
|
8
|
-
"main": "./dist/index.
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
9
|
"module": "./dist/index.js",
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
13
|
"types": "./dist/index.d.ts",
|
|
14
|
-
"
|
|
15
|
-
"require": "./dist/index.cjs"
|
|
14
|
+
"default": "./dist/index.js"
|
|
16
15
|
}
|
|
17
16
|
},
|
|
18
17
|
"files": [
|
|
19
18
|
"dist"
|
|
20
19
|
],
|
|
21
20
|
"scripts": {
|
|
22
|
-
"build": "tsup",
|
|
21
|
+
"build": "tsup && npm run typecheck",
|
|
22
|
+
"prepack": "npm run build && npm run typecheck",
|
|
23
|
+
"pack": "npm pack --dry-run",
|
|
24
|
+
"validate": "npm run lint && npm run test && npm run typecheck",
|
|
23
25
|
"dev": "tsup --watch",
|
|
24
26
|
"test": "vitest run",
|
|
25
27
|
"test:watch": "vitest",
|
package/dist/index.cjs
DELETED
|
@@ -1,603 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// src/config.ts
|
|
4
|
-
function resolveConfig(opts) {
|
|
5
|
-
const cfg = {
|
|
6
|
-
baseUrl: opts.baseUrl ?? "https://uat.mydupr.com/api",
|
|
7
|
-
version: opts.version ?? "v1.0",
|
|
8
|
-
timeoutMs: opts.timeoutMs ?? 3e4,
|
|
9
|
-
auth: opts.auth ?? { type: "none" },
|
|
10
|
-
userAgent: opts.userAgent ?? "dupr-js-client/0.1.0",
|
|
11
|
-
customFetch: opts.customFetch ?? globalThis.fetch.bind(globalThis),
|
|
12
|
-
retry: opts.retry === false ? false : {
|
|
13
|
-
maxRetries: opts.retry?.maxRetries ?? 3,
|
|
14
|
-
baseDelayMs: opts.retry?.baseDelayMs ?? 1e3,
|
|
15
|
-
maxDelayMs: opts.retry?.maxDelayMs ?? 3e4
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
if (opts.onRequest) cfg.onRequest = opts.onRequest;
|
|
19
|
-
if (opts.onResponse) cfg.onResponse = opts.onResponse;
|
|
20
|
-
return cfg;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// src/errors.ts
|
|
24
|
-
var DuprApiError = class extends Error {
|
|
25
|
-
constructor(message, statusCode, details, duprRequestId) {
|
|
26
|
-
super(message);
|
|
27
|
-
this.statusCode = statusCode;
|
|
28
|
-
this.details = details;
|
|
29
|
-
this.duprRequestId = duprRequestId;
|
|
30
|
-
this.name = "DuprApiError";
|
|
31
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
var AuthenticationError = class extends DuprApiError {
|
|
35
|
-
constructor(message, statusCode, details, duprRequestId) {
|
|
36
|
-
super(message, statusCode, details, duprRequestId);
|
|
37
|
-
this.name = "AuthenticationError";
|
|
38
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
var ValidationError = class extends DuprApiError {
|
|
42
|
-
constructor(message, statusCode, details, duprRequestId) {
|
|
43
|
-
super(message, statusCode, details, duprRequestId);
|
|
44
|
-
this.name = "ValidationError";
|
|
45
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
var NotFoundError = class extends DuprApiError {
|
|
49
|
-
constructor(message, statusCode, details, duprRequestId) {
|
|
50
|
-
super(message, statusCode, details, duprRequestId);
|
|
51
|
-
this.name = "NotFoundError";
|
|
52
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
var RateLimitError = class extends DuprApiError {
|
|
56
|
-
constructor(message, statusCode, details, duprRequestId) {
|
|
57
|
-
super(message, statusCode, details, duprRequestId);
|
|
58
|
-
this.name = "RateLimitError";
|
|
59
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
var ServerError = class extends DuprApiError {
|
|
63
|
-
constructor(message, statusCode, details, duprRequestId) {
|
|
64
|
-
super(message, statusCode, details, duprRequestId);
|
|
65
|
-
this.name = "ServerError";
|
|
66
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
async function buildError(res) {
|
|
70
|
-
let body;
|
|
71
|
-
const requestId = res.headers.get("x-request-id") ?? res.headers.get("x-dupr-request-id") ?? void 0;
|
|
72
|
-
try {
|
|
73
|
-
body = await res.json();
|
|
74
|
-
} catch {
|
|
75
|
-
}
|
|
76
|
-
const msg = (typeof body === "object" && body !== null && "message" in body && typeof body["message"] === "string" ? body["message"] : null) ?? `DUPR API error ${res.status}`;
|
|
77
|
-
switch (true) {
|
|
78
|
-
case (res.status === 401 || res.status === 403):
|
|
79
|
-
return new AuthenticationError(msg, res.status, body, requestId);
|
|
80
|
-
case res.status === 404:
|
|
81
|
-
return new NotFoundError(msg, res.status, body, requestId);
|
|
82
|
-
case res.status === 400:
|
|
83
|
-
return new ValidationError(msg, res.status, body, requestId);
|
|
84
|
-
case res.status === 429:
|
|
85
|
-
return new RateLimitError(msg, res.status, body, requestId);
|
|
86
|
-
case res.status >= 500:
|
|
87
|
-
return new ServerError(msg, res.status, body, requestId);
|
|
88
|
-
default:
|
|
89
|
-
return new DuprApiError(msg, res.status, body, requestId);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// src/http.ts
|
|
94
|
-
function sleep(ms) {
|
|
95
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
96
|
-
}
|
|
97
|
-
function retryDelayMs(attempt, baseDelayMs, maxDelayMs) {
|
|
98
|
-
const exp = Math.min(baseDelayMs * 2 ** attempt, maxDelayMs);
|
|
99
|
-
return exp * (0.8 + Math.random() * 0.4);
|
|
100
|
-
}
|
|
101
|
-
function isRetryable(err) {
|
|
102
|
-
if (err instanceof RateLimitError) return true;
|
|
103
|
-
if (err instanceof ServerError) return true;
|
|
104
|
-
if (err instanceof TypeError) return true;
|
|
105
|
-
return false;
|
|
106
|
-
}
|
|
107
|
-
var HttpClient = class {
|
|
108
|
-
constructor(config) {
|
|
109
|
-
this.config = config;
|
|
110
|
-
this.token = null;
|
|
111
|
-
this.tokenExpiresAt = 0;
|
|
112
|
-
}
|
|
113
|
-
async getBearerToken() {
|
|
114
|
-
if (this.config.overrideBearerToken) {
|
|
115
|
-
return this.config.overrideBearerToken;
|
|
116
|
-
}
|
|
117
|
-
if (this.config.auth.type === "staticBearer") {
|
|
118
|
-
return this.config.auth.bearerToken;
|
|
119
|
-
}
|
|
120
|
-
if (this.config.auth.type !== "clientCredentials") {
|
|
121
|
-
throw new AuthenticationError("No auth configured \u2014 set auth in DuprClientOptions or call setBearerToken()", 401);
|
|
122
|
-
}
|
|
123
|
-
if (this.token && Date.now() < this.tokenExpiresAt) {
|
|
124
|
-
return this.token;
|
|
125
|
-
}
|
|
126
|
-
const { clientKey, clientSecret } = this.config.auth;
|
|
127
|
-
const encoded = Buffer.from(`${clientKey}:${clientSecret}`).toString("base64");
|
|
128
|
-
const url = `${this.config.baseUrl}/auth/${this.config.version}/token`;
|
|
129
|
-
const start = Date.now();
|
|
130
|
-
const res = await this.config.customFetch(url, {
|
|
131
|
-
method: "POST",
|
|
132
|
-
headers: {
|
|
133
|
-
"x-authorization": encoded,
|
|
134
|
-
"User-Agent": this.config.userAgent
|
|
135
|
-
},
|
|
136
|
-
signal: AbortSignal.timeout(this.config.timeoutMs)
|
|
137
|
-
});
|
|
138
|
-
this.config.onResponse?.({ status: res.status, url, durationMs: Date.now() - start });
|
|
139
|
-
if (!res.ok) throw await buildError(res);
|
|
140
|
-
const body = await res.json();
|
|
141
|
-
this.token = body.token ?? body.accessToken ?? null;
|
|
142
|
-
if (!this.token) throw new AuthenticationError("Token response contained no token", 401);
|
|
143
|
-
const ttlSec = body.expiresIn ?? 3600;
|
|
144
|
-
this.tokenExpiresAt = Date.now() + (ttlSec - 60) * 1e3;
|
|
145
|
-
return this.token;
|
|
146
|
-
}
|
|
147
|
-
async get(path, init) {
|
|
148
|
-
return this.request("GET", path, init);
|
|
149
|
-
}
|
|
150
|
-
async post(path, body, init) {
|
|
151
|
-
const extra = { headers: { "Content-Type": "application/json", ...init?.headers ?? {} } };
|
|
152
|
-
if (body !== void 0) extra.body = JSON.stringify(body);
|
|
153
|
-
return this.request("POST", path, { ...init, ...extra });
|
|
154
|
-
}
|
|
155
|
-
async delete(path, body, init) {
|
|
156
|
-
const extra = { headers: { "Content-Type": "application/json", ...init?.headers ?? {} } };
|
|
157
|
-
if (body !== void 0) extra.body = JSON.stringify(body);
|
|
158
|
-
return this.request("DELETE", path, { ...init, ...extra });
|
|
159
|
-
}
|
|
160
|
-
async request(method, path, init) {
|
|
161
|
-
const retryCfg = this.config.retry;
|
|
162
|
-
const maxAttempts = retryCfg === false ? 1 : retryCfg.maxRetries + 1;
|
|
163
|
-
let lastErr;
|
|
164
|
-
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
165
|
-
try {
|
|
166
|
-
return await this.rawRequest(method, path, init);
|
|
167
|
-
} catch (err) {
|
|
168
|
-
lastErr = err;
|
|
169
|
-
if (attempt >= maxAttempts - 1) break;
|
|
170
|
-
if (!isRetryable(err)) break;
|
|
171
|
-
if (retryCfg === false) break;
|
|
172
|
-
let delay;
|
|
173
|
-
if (err instanceof RateLimitError) {
|
|
174
|
-
const retryAfterSec = err.details !== null && typeof err.details === "object" && "retryAfterSeconds" in err.details ? Number(err.details.retryAfterSeconds) : NaN;
|
|
175
|
-
delay = Number.isFinite(retryAfterSec) && retryAfterSec > 0 ? retryAfterSec * 1e3 : retryDelayMs(attempt, retryCfg.baseDelayMs, retryCfg.maxDelayMs);
|
|
176
|
-
} else {
|
|
177
|
-
delay = retryDelayMs(attempt, retryCfg.baseDelayMs, retryCfg.maxDelayMs);
|
|
178
|
-
}
|
|
179
|
-
await sleep(delay);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
throw lastErr;
|
|
183
|
-
}
|
|
184
|
-
async rawRequest(method, path, init) {
|
|
185
|
-
const token = await this.getBearerToken();
|
|
186
|
-
const url = `${this.config.baseUrl}${path}`;
|
|
187
|
-
const headers = {
|
|
188
|
-
Authorization: `Bearer ${token}`,
|
|
189
|
-
"User-Agent": this.config.userAgent,
|
|
190
|
-
...init?.headers ?? {}
|
|
191
|
-
};
|
|
192
|
-
this.config.onRequest?.({ method, url, headers });
|
|
193
|
-
const start = Date.now();
|
|
194
|
-
const res = await this.config.customFetch(url, {
|
|
195
|
-
method,
|
|
196
|
-
...init,
|
|
197
|
-
headers,
|
|
198
|
-
signal: AbortSignal.timeout(this.config.timeoutMs)
|
|
199
|
-
});
|
|
200
|
-
this.config.onResponse?.({ status: res.status, url, durationMs: Date.now() - start });
|
|
201
|
-
if (!res.ok) {
|
|
202
|
-
const err = await buildError(res);
|
|
203
|
-
if (err instanceof RateLimitError) {
|
|
204
|
-
const retryAfter = res.headers.get("Retry-After");
|
|
205
|
-
if (retryAfter) {
|
|
206
|
-
err.details = typeof err.details === "object" && err.details !== null ? { ...err.details, retryAfterSeconds: Number(retryAfter) } : { retryAfterSeconds: Number(retryAfter) };
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
throw err;
|
|
210
|
-
}
|
|
211
|
-
if (res.status === 204 || res.headers.get("content-length") === "0") {
|
|
212
|
-
return void 0;
|
|
213
|
-
}
|
|
214
|
-
return res.json();
|
|
215
|
-
}
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
// src/auth.ts
|
|
219
|
-
var AuthModule = class {
|
|
220
|
-
constructor(http, config) {
|
|
221
|
-
this.http = http;
|
|
222
|
-
this.config = config;
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Explicitly request a new access token using client credentials.
|
|
226
|
-
* Normally you don't need to call this — the HTTP client handles token refresh automatically.
|
|
227
|
-
*/
|
|
228
|
-
async getToken() {
|
|
229
|
-
if (this.config.auth.type !== "clientCredentials") {
|
|
230
|
-
throw new AuthenticationError("getToken() requires clientCredentials auth mode", 401);
|
|
231
|
-
}
|
|
232
|
-
const { clientKey, clientSecret } = this.config.auth;
|
|
233
|
-
const encoded = Buffer.from(`${clientKey}:${clientSecret}`).toString("base64");
|
|
234
|
-
const url = `${this.config.baseUrl}/auth/${this.config.version}/token`;
|
|
235
|
-
const res = await this.config.customFetch(url, {
|
|
236
|
-
method: "POST",
|
|
237
|
-
headers: {
|
|
238
|
-
"x-authorization": encoded,
|
|
239
|
-
"User-Agent": this.config.userAgent
|
|
240
|
-
},
|
|
241
|
-
signal: AbortSignal.timeout(this.config.timeoutMs)
|
|
242
|
-
});
|
|
243
|
-
if (!res.ok) {
|
|
244
|
-
const body = await res.json().catch(() => void 0);
|
|
245
|
-
throw new AuthenticationError(
|
|
246
|
-
body?.["message"] ?? `Auth failed: ${res.status}`,
|
|
247
|
-
res.status,
|
|
248
|
-
body
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
return res.json();
|
|
252
|
-
}
|
|
253
|
-
// ── Authorization Code Flow ───────────────────────────────────────────────
|
|
254
|
-
//
|
|
255
|
-
// Use this flow to let end-users authorise your app to act on their behalf
|
|
256
|
-
// (e.g. the "Connect DUPR" button). The user is redirected to DUPR's login
|
|
257
|
-
// page, then back to your redirectUri with an authorization code.
|
|
258
|
-
//
|
|
259
|
-
// NOTE: This requires a DUPR OAuth application with an authorization endpoint
|
|
260
|
-
// separate from the Partner API client credentials. Confirm the exact
|
|
261
|
-
// authorization URL with DUPR support.
|
|
262
|
-
//
|
|
263
|
-
// Typical flow:
|
|
264
|
-
// 1. client.auth.getAuthorizationUrl({ redirectUri, state }) → redirect user
|
|
265
|
-
// 2. User approves → DUPR calls back to redirectUri?code=xxx&state=yyy
|
|
266
|
-
// 3. client.auth.exchangeCode({ code, redirectUri }) → tokens
|
|
267
|
-
// 4. Store access_token + refresh_token; call client.setBearerToken(access_token)
|
|
268
|
-
// 5. When access_token expires: client.auth.refreshToken(refresh_token)
|
|
269
|
-
/**
|
|
270
|
-
* Build the DUPR authorization URL to redirect the user to for login.
|
|
271
|
-
* The `authorizationUrl` config option must be set (see above note).
|
|
272
|
-
*/
|
|
273
|
-
getAuthorizationUrl(params) {
|
|
274
|
-
const authUrl = this.config.authorizationUrl;
|
|
275
|
-
if (!authUrl) {
|
|
276
|
-
throw new Error(
|
|
277
|
-
"authorizationUrl is not configured. Pass it in DuprClientOptions to use the Authorization Code flow."
|
|
278
|
-
);
|
|
279
|
-
}
|
|
280
|
-
const url = new URL(authUrl);
|
|
281
|
-
const clientId = this.config.auth.type === "clientCredentials" ? this.config.auth.clientKey : "";
|
|
282
|
-
url.searchParams.set("response_type", "code");
|
|
283
|
-
url.searchParams.set("client_id", clientId);
|
|
284
|
-
url.searchParams.set("redirect_uri", params.redirectUri);
|
|
285
|
-
if (params.scopes?.length) url.searchParams.set("scope", params.scopes.join(" "));
|
|
286
|
-
if (params.state) url.searchParams.set("state", params.state);
|
|
287
|
-
return url.toString();
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* Exchange an authorization code (from the OAuth callback) for access + refresh tokens.
|
|
291
|
-
* Uses `POST /auth/{version}/token` with `grant_type=authorization_code`.
|
|
292
|
-
*/
|
|
293
|
-
async exchangeCode(params) {
|
|
294
|
-
if (this.config.auth.type !== "clientCredentials") {
|
|
295
|
-
throw new AuthenticationError("exchangeCode() requires clientCredentials auth configured with clientKey/clientSecret", 401);
|
|
296
|
-
}
|
|
297
|
-
const { clientKey, clientSecret } = this.config.auth;
|
|
298
|
-
const url = `${this.config.baseUrl}/auth/${this.config.version}/token`;
|
|
299
|
-
const body = new URLSearchParams({
|
|
300
|
-
grant_type: "authorization_code",
|
|
301
|
-
code: params.code,
|
|
302
|
-
redirect_uri: params.redirectUri,
|
|
303
|
-
client_id: clientKey,
|
|
304
|
-
client_secret: clientSecret
|
|
305
|
-
});
|
|
306
|
-
const res = await this.config.customFetch(url, {
|
|
307
|
-
method: "POST",
|
|
308
|
-
headers: {
|
|
309
|
-
"Content-Type": "application/x-www-form-urlencoded",
|
|
310
|
-
"User-Agent": this.config.userAgent
|
|
311
|
-
},
|
|
312
|
-
body: body.toString(),
|
|
313
|
-
signal: AbortSignal.timeout(this.config.timeoutMs)
|
|
314
|
-
});
|
|
315
|
-
if (!res.ok) {
|
|
316
|
-
const errBody = await res.json().catch(() => void 0);
|
|
317
|
-
throw new AuthenticationError(
|
|
318
|
-
errBody?.["message"] ?? `Code exchange failed: ${res.status}`,
|
|
319
|
-
res.status,
|
|
320
|
-
errBody
|
|
321
|
-
);
|
|
322
|
-
}
|
|
323
|
-
return res.json();
|
|
324
|
-
}
|
|
325
|
-
/**
|
|
326
|
-
* Obtain a new access token using a refresh token from a previous Authorization Code flow.
|
|
327
|
-
* Uses `POST /auth/{version}/token` with `grant_type=refresh_token`.
|
|
328
|
-
*/
|
|
329
|
-
async refreshToken(refreshToken) {
|
|
330
|
-
if (this.config.auth.type !== "clientCredentials") {
|
|
331
|
-
throw new AuthenticationError("refreshToken() requires clientCredentials auth configured", 401);
|
|
332
|
-
}
|
|
333
|
-
const { clientKey, clientSecret } = this.config.auth;
|
|
334
|
-
const url = `${this.config.baseUrl}/auth/${this.config.version}/token`;
|
|
335
|
-
const body = new URLSearchParams({
|
|
336
|
-
grant_type: "refresh_token",
|
|
337
|
-
refresh_token: refreshToken,
|
|
338
|
-
client_id: clientKey,
|
|
339
|
-
client_secret: clientSecret
|
|
340
|
-
});
|
|
341
|
-
const res = await this.config.customFetch(url, {
|
|
342
|
-
method: "POST",
|
|
343
|
-
headers: {
|
|
344
|
-
"Content-Type": "application/x-www-form-urlencoded",
|
|
345
|
-
"User-Agent": this.config.userAgent
|
|
346
|
-
},
|
|
347
|
-
body: body.toString(),
|
|
348
|
-
signal: AbortSignal.timeout(this.config.timeoutMs)
|
|
349
|
-
});
|
|
350
|
-
if (!res.ok) {
|
|
351
|
-
const errBody = await res.json().catch(() => void 0);
|
|
352
|
-
throw new AuthenticationError(
|
|
353
|
-
errBody?.["message"] ?? `Token refresh failed: ${res.status}`,
|
|
354
|
-
res.status,
|
|
355
|
-
errBody
|
|
356
|
-
);
|
|
357
|
-
}
|
|
358
|
-
return res.json();
|
|
359
|
-
}
|
|
360
|
-
};
|
|
361
|
-
|
|
362
|
-
// src/resources/users.ts
|
|
363
|
-
var UsersModule = class {
|
|
364
|
-
constructor(http, cfg) {
|
|
365
|
-
this.http = http;
|
|
366
|
-
this.cfg = cfg;
|
|
367
|
-
}
|
|
368
|
-
/** GET /user/{version}/{id} — basic player profile */
|
|
369
|
-
getUser(duprId) {
|
|
370
|
-
return this.http.get(`/user/${this.cfg.version}/${duprId}`);
|
|
371
|
-
}
|
|
372
|
-
/** GET /user/{version}/{id}/details — extended profile (requires USER_EMAIL::VIEW permission) */
|
|
373
|
-
getExtendedUser(duprId) {
|
|
374
|
-
return this.http.get(`/user/${this.cfg.version}/${duprId}/details`);
|
|
375
|
-
}
|
|
376
|
-
/** GET /user/{version}/{id}/clubs — club memberships for a player */
|
|
377
|
-
getClubMemberships(duprId) {
|
|
378
|
-
return this.http.get(`/user/${this.cfg.version}/${duprId}/clubs`);
|
|
379
|
-
}
|
|
380
|
-
/** POST /user/{version}/search — full-text player search with optional filters */
|
|
381
|
-
search(req) {
|
|
382
|
-
return this.http.post(`/user/${this.cfg.version}/search`, req);
|
|
383
|
-
}
|
|
384
|
-
/** POST /user/{version}/batch — fetch multiple players by DUPR ID in one request */
|
|
385
|
-
getBatch(req) {
|
|
386
|
-
return this.http.post(`/user/${this.cfg.version}/batch`, req);
|
|
387
|
-
}
|
|
388
|
-
/** POST /user/{version}/invite — pre-generate a DUPR ID and send an invite email */
|
|
389
|
-
invite(req) {
|
|
390
|
-
return this.http.post(`/user/${this.cfg.version}/invite`, req);
|
|
391
|
-
}
|
|
392
|
-
/** POST /user/{version}/subscription/grants — grant a subscription to a user */
|
|
393
|
-
grantSubscription(req) {
|
|
394
|
-
return this.http.post(`/user/${this.cfg.version}/subscription/grants`, req);
|
|
395
|
-
}
|
|
396
|
-
// ── Provisional ratings ──────────────────────────────────────
|
|
397
|
-
/** POST /user/{version}/provisional_rating — get provisional ratings for a player */
|
|
398
|
-
getProvisionalRating(req) {
|
|
399
|
-
return this.http.post(`/user/${this.cfg.version}/provisional_rating`, req);
|
|
400
|
-
}
|
|
401
|
-
/** POST /user/{version}/provisional_rating/create */
|
|
402
|
-
createProvisionalRating(req) {
|
|
403
|
-
return this.http.post(`/user/${this.cfg.version}/provisional_rating/create`, req);
|
|
404
|
-
}
|
|
405
|
-
/** POST /user/{version}/provisional_rating/update */
|
|
406
|
-
updateProvisionalRating(req) {
|
|
407
|
-
return this.http.post(`/user/${this.cfg.version}/provisional_rating/update`, req);
|
|
408
|
-
}
|
|
409
|
-
/** DELETE /user/{version}/provisional_rating/delete */
|
|
410
|
-
deleteProvisionalRating(req) {
|
|
411
|
-
return this.http.delete(`/user/${this.cfg.version}/provisional_rating/delete`, req);
|
|
412
|
-
}
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
// src/resources/players.ts
|
|
416
|
-
var PlayersModule = class {
|
|
417
|
-
constructor(http, cfg) {
|
|
418
|
-
this.http = http;
|
|
419
|
-
this.cfg = cfg;
|
|
420
|
-
}
|
|
421
|
-
/** POST /{version}/player/duprid-by-email — resolve a DUPR ID from an email address */
|
|
422
|
-
getDuprIdByEmail(req) {
|
|
423
|
-
return this.http.post(`/${this.cfg.version}/player/duprid-by-email`, req);
|
|
424
|
-
}
|
|
425
|
-
};
|
|
426
|
-
|
|
427
|
-
// src/resources/playerRating.ts
|
|
428
|
-
var PlayerRatingModule = class {
|
|
429
|
-
constructor(http, cfg) {
|
|
430
|
-
this.http = http;
|
|
431
|
-
this.cfg = cfg;
|
|
432
|
-
}
|
|
433
|
-
/** POST /history — get rating history for a player */
|
|
434
|
-
getHistory(req) {
|
|
435
|
-
return this.http.post(`/history`, req);
|
|
436
|
-
}
|
|
437
|
-
/** GET /{version}/subscribe/rating-changes — list currently subscribed DUPR IDs */
|
|
438
|
-
getSubscriptions() {
|
|
439
|
-
return this.http.get(`/${this.cfg.version}/subscribe/rating-changes`);
|
|
440
|
-
}
|
|
441
|
-
/** POST /{version}/subscribe/rating-changes — subscribe to rating-change events for a list of players */
|
|
442
|
-
subscribe(req) {
|
|
443
|
-
return this.http.post(`/${this.cfg.version}/subscribe/rating-changes`, req);
|
|
444
|
-
}
|
|
445
|
-
/** DELETE /{version}/subscribe/rating-changes — unsubscribe from rating-change events */
|
|
446
|
-
unsubscribe(req) {
|
|
447
|
-
return this.http.delete(`/${this.cfg.version}/subscribe/rating-changes`, req);
|
|
448
|
-
}
|
|
449
|
-
};
|
|
450
|
-
|
|
451
|
-
// src/resources/matches.ts
|
|
452
|
-
var MatchesModule = class {
|
|
453
|
-
constructor(http, cfg) {
|
|
454
|
-
this.http = http;
|
|
455
|
-
this.cfg = cfg;
|
|
456
|
-
}
|
|
457
|
-
/** GET /match/{version}/{id} — view a single match */
|
|
458
|
-
get(matchId) {
|
|
459
|
-
return this.http.get(`/match/${this.cfg.version}/${matchId}`);
|
|
460
|
-
}
|
|
461
|
-
/** POST /match/{version}/create — submit a new match result */
|
|
462
|
-
create(match) {
|
|
463
|
-
return this.http.post(`/match/${this.cfg.version}/create`, match);
|
|
464
|
-
}
|
|
465
|
-
/** POST /match/{version}/batch — submit multiple match results in one call */
|
|
466
|
-
createBulk(matches) {
|
|
467
|
-
return this.http.post(`/match/${this.cfg.version}/batch`, matches);
|
|
468
|
-
}
|
|
469
|
-
/** POST /match/{version}/update — update an existing match */
|
|
470
|
-
update(req) {
|
|
471
|
-
return this.http.post(`/match/${this.cfg.version}/update`, req);
|
|
472
|
-
}
|
|
473
|
-
/** DELETE /match/{version}/delete — delete a match */
|
|
474
|
-
delete(req) {
|
|
475
|
-
return this.http.delete(`/match/${this.cfg.version}/delete`, req);
|
|
476
|
-
}
|
|
477
|
-
/** POST /match/{version}/annotate — attach vendor-specific metadata to a match */
|
|
478
|
-
annotate(req) {
|
|
479
|
-
return this.http.post(`/match/${this.cfg.version}/annotate`, req);
|
|
480
|
-
}
|
|
481
|
-
/** DELETE /match/{version}/annotate/{matchId} — remove a match annotation */
|
|
482
|
-
deleteAnnotation(matchId) {
|
|
483
|
-
return this.http.delete(`/match/${this.cfg.version}/annotate/${matchId}`);
|
|
484
|
-
}
|
|
485
|
-
/** POST /match/history/search — search a player's match history */
|
|
486
|
-
searchHistory(req) {
|
|
487
|
-
return this.http.post(`/match/history/search`, req);
|
|
488
|
-
}
|
|
489
|
-
};
|
|
490
|
-
|
|
491
|
-
// src/resources/clubs.ts
|
|
492
|
-
var ClubsModule = class {
|
|
493
|
-
constructor(http, cfg) {
|
|
494
|
-
this.http = http;
|
|
495
|
-
this.cfg = cfg;
|
|
496
|
-
}
|
|
497
|
-
/** POST /club/{version}/members — get ratings for all members of a club */
|
|
498
|
-
membersRating(req) {
|
|
499
|
-
return this.http.post(`/club/${this.cfg.version}/members`, req);
|
|
500
|
-
}
|
|
501
|
-
/** POST /club/{version}/match/search — search matches associated with a club */
|
|
502
|
-
searchMatches(req) {
|
|
503
|
-
return this.http.post(`/club/${this.cfg.version}/match/search`, req);
|
|
504
|
-
}
|
|
505
|
-
};
|
|
506
|
-
|
|
507
|
-
// src/resources/events.ts
|
|
508
|
-
var EventsModule = class {
|
|
509
|
-
constructor(http, cfg) {
|
|
510
|
-
this.http = http;
|
|
511
|
-
this.cfg = cfg;
|
|
512
|
-
}
|
|
513
|
-
/** POST /events/{version}/create */
|
|
514
|
-
create(req) {
|
|
515
|
-
return this.http.post(`/events/${this.cfg.version}/create`, req);
|
|
516
|
-
}
|
|
517
|
-
/** GET /events/{version}/get */
|
|
518
|
-
get(req) {
|
|
519
|
-
return this.http.post(`/events/${this.cfg.version}/get`, req);
|
|
520
|
-
}
|
|
521
|
-
/** POST /events/{version}/update */
|
|
522
|
-
update(req) {
|
|
523
|
-
return this.http.post(`/events/${this.cfg.version}/update`, req);
|
|
524
|
-
}
|
|
525
|
-
/** POST /events/{version}/delete */
|
|
526
|
-
delete(req) {
|
|
527
|
-
return this.http.post(`/events/${this.cfg.version}/delete`, req);
|
|
528
|
-
}
|
|
529
|
-
};
|
|
530
|
-
|
|
531
|
-
// src/resources/webhooks.ts
|
|
532
|
-
var WebhooksModule = class {
|
|
533
|
-
constructor(http, cfg) {
|
|
534
|
-
this.http = http;
|
|
535
|
-
this.cfg = cfg;
|
|
536
|
-
}
|
|
537
|
-
/** POST /{version}/webhook — register a webhook endpoint */
|
|
538
|
-
register(req) {
|
|
539
|
-
return this.http.post(`/${this.cfg.version}/webhook`, req);
|
|
540
|
-
}
|
|
541
|
-
/** GET /{version}/topic — list all available webhook topics */
|
|
542
|
-
getTopics() {
|
|
543
|
-
return this.http.get(`/${this.cfg.version}/topic`);
|
|
544
|
-
}
|
|
545
|
-
/** GET /{version}/webhook/schema — list available webhook schemas */
|
|
546
|
-
listSchemas() {
|
|
547
|
-
return this.http.get(`/${this.cfg.version}/webhook/schema`);
|
|
548
|
-
}
|
|
549
|
-
/** GET /{version}/webhook/schema/{topic} — get the JSON schema for a specific topic */
|
|
550
|
-
getSchema(topic) {
|
|
551
|
-
return this.http.get(`/${this.cfg.version}/webhook/schema/${topic}`);
|
|
552
|
-
}
|
|
553
|
-
/** POST /user/{version}/subscribe/webhook-event — subscribe specific users to a webhook topic */
|
|
554
|
-
subscribeUsers(req) {
|
|
555
|
-
return this.http.post(`/user/${this.cfg.version}/subscribe/webhook-event`, req);
|
|
556
|
-
}
|
|
557
|
-
/** DELETE /user/{version}/subscribe/webhook-event — unsubscribe specific users from a webhook topic */
|
|
558
|
-
unsubscribeUsers(req) {
|
|
559
|
-
return this.http.delete(`/user/${this.cfg.version}/subscribe/webhook-event`, req);
|
|
560
|
-
}
|
|
561
|
-
};
|
|
562
|
-
|
|
563
|
-
// src/client.ts
|
|
564
|
-
var DuprClient = class {
|
|
565
|
-
constructor(opts = {}) {
|
|
566
|
-
this.config = resolveConfig(opts);
|
|
567
|
-
const http = new HttpClient(this.config);
|
|
568
|
-
this.auth = new AuthModule(http, this.config);
|
|
569
|
-
this.users = new UsersModule(http, this.config);
|
|
570
|
-
this.players = new PlayersModule(http, this.config);
|
|
571
|
-
this.playerRating = new PlayerRatingModule(http, this.config);
|
|
572
|
-
this.matches = new MatchesModule(http, this.config);
|
|
573
|
-
this.clubs = new ClubsModule(http, this.config);
|
|
574
|
-
this.events = new EventsModule(http, this.config);
|
|
575
|
-
this.webhooks = new WebhooksModule(http, this.config);
|
|
576
|
-
}
|
|
577
|
-
/** Override the bearer token at runtime — useful when your backend handles auth separately. */
|
|
578
|
-
setBearerToken(token) {
|
|
579
|
-
this.config.overrideBearerToken = token;
|
|
580
|
-
}
|
|
581
|
-
/** Clear the runtime bearer token override and fall back to configured auth. */
|
|
582
|
-
clearBearerToken() {
|
|
583
|
-
delete this.config.overrideBearerToken;
|
|
584
|
-
}
|
|
585
|
-
};
|
|
586
|
-
|
|
587
|
-
exports.AuthModule = AuthModule;
|
|
588
|
-
exports.AuthenticationError = AuthenticationError;
|
|
589
|
-
exports.ClubsModule = ClubsModule;
|
|
590
|
-
exports.DuprApiError = DuprApiError;
|
|
591
|
-
exports.DuprClient = DuprClient;
|
|
592
|
-
exports.EventsModule = EventsModule;
|
|
593
|
-
exports.MatchesModule = MatchesModule;
|
|
594
|
-
exports.NotFoundError = NotFoundError;
|
|
595
|
-
exports.PlayerRatingModule = PlayerRatingModule;
|
|
596
|
-
exports.PlayersModule = PlayersModule;
|
|
597
|
-
exports.RateLimitError = RateLimitError;
|
|
598
|
-
exports.ServerError = ServerError;
|
|
599
|
-
exports.UsersModule = UsersModule;
|
|
600
|
-
exports.ValidationError = ValidationError;
|
|
601
|
-
exports.WebhooksModule = WebhooksModule;
|
|
602
|
-
//# sourceMappingURL=index.cjs.map
|
|
603
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts","../src/errors.ts","../src/http.ts","../src/auth.ts","../src/resources/users.ts","../src/resources/players.ts","../src/resources/playerRating.ts","../src/resources/matches.ts","../src/resources/clubs.ts","../src/resources/events.ts","../src/resources/webhooks.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["export type AuthMode =\r\n | { type: \"clientCredentials\"; clientKey: string; clientSecret: string }\r\n | { type: \"staticBearer\"; bearerToken: string }\r\n | { type: \"none\" };\r\n\r\nexport interface RequestInfo {\r\n method: string;\r\n url: string;\r\n headers: Record<string, string>;\r\n}\r\n\r\nexport interface ResponseInfo {\r\n status: number;\r\n url: string;\r\n durationMs: number;\r\n}\r\n\r\nexport interface RetryOptions {\r\n /** Max number of retry attempts after the initial failure. @default 3 */\r\n maxRetries?: number;\r\n /** Base delay in ms before the first retry. Doubles on each attempt. @default 1_000 */\r\n baseDelayMs?: number;\r\n /** Max delay cap in ms (prevents infinite backoff). @default 30_000 */\r\n maxDelayMs?: number;\r\n}\r\n\r\nexport interface DuprClientOptions {\r\n /** @default \"https://uat.mydupr.com/api\" */\r\n baseUrl?: string;\r\n /** API version prefix used in all paths. @default \"v1.0\" */\r\n version?: string;\r\n /** Request timeout in milliseconds. @default 30_000 */\r\n timeoutMs?: number;\r\n auth?: AuthMode;\r\n /** Custom User-Agent header. */\r\n userAgent?: string;\r\n /** Inject a custom fetch implementation (useful for testing or polyfilling). */\r\n customFetch?: typeof fetch;\r\n /** Called before every request. Useful for logging or tracing. */\r\n onRequest?: (info: RequestInfo) => void;\r\n /** Called after every response (including errors). */\r\n onResponse?: (info: ResponseInfo) => void;\r\n /** Retry behaviour for transient errors (5xx, network failures, 429). Pass `false` to disable. */\r\n retry?: RetryOptions | false;\r\n}\r\n\r\nexport interface ResolvedRetryOptions {\r\n maxRetries: number;\r\n baseDelayMs: number;\r\n maxDelayMs: number;\r\n}\r\n\r\nexport interface ResolvedConfig {\r\n baseUrl: string;\r\n version: string;\r\n timeoutMs: number;\r\n auth: AuthMode;\r\n userAgent: string;\r\n customFetch: typeof fetch;\r\n retry: ResolvedRetryOptions | false;\r\n onRequest?: (info: RequestInfo) => void;\r\n onResponse?: (info: ResponseInfo) => void;\r\n /** Runtime override for the bearer token — set via `client.setBearerToken()`. */\r\n overrideBearerToken?: string;\r\n}\r\n\r\nexport function resolveConfig(opts: DuprClientOptions): ResolvedConfig {\r\n const cfg: ResolvedConfig = {\r\n baseUrl: opts.baseUrl ?? \"https://uat.mydupr.com/api\",\r\n version: opts.version ?? \"v1.0\",\r\n timeoutMs: opts.timeoutMs ?? 30_000,\r\n auth: opts.auth ?? { type: \"none\" },\r\n userAgent: opts.userAgent ?? \"dupr-js-client/0.1.0\",\r\n customFetch: opts.customFetch ?? globalThis.fetch.bind(globalThis),\r\n retry:\r\n opts.retry === false\r\n ? false\r\n : {\r\n maxRetries: opts.retry?.maxRetries ?? 3,\r\n baseDelayMs: opts.retry?.baseDelayMs ?? 1_000,\r\n maxDelayMs: opts.retry?.maxDelayMs ?? 30_000,\r\n },\r\n };\r\n if (opts.onRequest) cfg.onRequest = opts.onRequest;\r\n if (opts.onResponse) cfg.onResponse = opts.onResponse;\r\n return cfg;\r\n}\r\n","export class DuprApiError extends Error {\r\n constructor(\r\n message: string,\r\n public readonly statusCode: number,\r\n public readonly details?: unknown,\r\n public readonly duprRequestId?: string,\r\n ) {\r\n super(message);\r\n this.name = \"DuprApiError\";\r\n // Maintain proper prototype chain in transpiled environments\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n }\r\n}\r\n\r\nexport class AuthenticationError extends DuprApiError {\r\n constructor(message: string, statusCode: number, details?: unknown, duprRequestId?: string) {\r\n super(message, statusCode, details, duprRequestId);\r\n this.name = \"AuthenticationError\";\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n }\r\n}\r\n\r\nexport class ValidationError extends DuprApiError {\r\n constructor(message: string, statusCode: number, details?: unknown, duprRequestId?: string) {\r\n super(message, statusCode, details, duprRequestId);\r\n this.name = \"ValidationError\";\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n }\r\n}\r\n\r\nexport class NotFoundError extends DuprApiError {\r\n constructor(message: string, statusCode: number, details?: unknown, duprRequestId?: string) {\r\n super(message, statusCode, details, duprRequestId);\r\n this.name = \"NotFoundError\";\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n }\r\n}\r\n\r\nexport class RateLimitError extends DuprApiError {\r\n constructor(message: string, statusCode: number, details?: unknown, duprRequestId?: string) {\r\n super(message, statusCode, details, duprRequestId);\r\n this.name = \"RateLimitError\";\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n }\r\n}\r\n\r\nexport class ServerError extends DuprApiError {\r\n constructor(message: string, statusCode: number, details?: unknown, duprRequestId?: string) {\r\n super(message, statusCode, details, duprRequestId);\r\n this.name = \"ServerError\";\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n }\r\n}\r\n\r\nexport async function buildError(res: Response): Promise<DuprApiError> {\r\n let body: unknown;\r\n const requestId = res.headers.get(\"x-request-id\") ?? res.headers.get(\"x-dupr-request-id\") ?? undefined;\r\n\r\n try {\r\n body = await res.json();\r\n } catch {\r\n // non-JSON body — leave body undefined\r\n }\r\n\r\n const msg =\r\n (typeof body === \"object\" && body !== null && \"message\" in body && typeof (body as Record<string, unknown>)[\"message\"] === \"string\"\r\n ? (body as Record<string, unknown>)[\"message\"] as string\r\n : null) ??\r\n `DUPR API error ${res.status}`;\r\n\r\n switch (true) {\r\n case res.status === 401 || res.status === 403:\r\n return new AuthenticationError(msg, res.status, body, requestId);\r\n case res.status === 404:\r\n return new NotFoundError(msg, res.status, body, requestId);\r\n case res.status === 400:\r\n return new ValidationError(msg, res.status, body, requestId);\r\n case res.status === 429:\r\n return new RateLimitError(msg, res.status, body, requestId);\r\n case res.status >= 500:\r\n return new ServerError(msg, res.status, body, requestId);\r\n default:\r\n return new DuprApiError(msg, res.status, body, requestId);\r\n }\r\n}\r\n","import { ResolvedConfig } from \"./config.js\";\r\nimport { AuthenticationError, buildError, RateLimitError, ServerError } from \"./errors.js\";\r\n\r\nfunction sleep(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n}\r\n\r\nfunction retryDelayMs(attempt: number, baseDelayMs: number, maxDelayMs: number): number {\r\n // Exponential backoff with ±20% jitter to avoid thundering herd\r\n const exp = Math.min(baseDelayMs * 2 ** attempt, maxDelayMs);\r\n return exp * (0.8 + Math.random() * 0.4);\r\n}\r\n\r\nfunction isRetryable(err: unknown): boolean {\r\n if (err instanceof RateLimitError) return true;\r\n if (err instanceof ServerError) return true;\r\n // Network-level failures (fetch throws a TypeError on connection refused etc.)\r\n if (err instanceof TypeError) return true;\r\n return false;\r\n}\r\n\r\nexport class HttpClient {\r\n private token: string | null = null;\r\n private tokenExpiresAt = 0;\r\n\r\n constructor(private readonly config: ResolvedConfig) {}\r\n\r\n private async getBearerToken(): Promise<string> {\r\n if (this.config.overrideBearerToken) {\r\n return this.config.overrideBearerToken;\r\n }\r\n if (this.config.auth.type === \"staticBearer\") {\r\n return this.config.auth.bearerToken;\r\n }\r\n if (this.config.auth.type !== \"clientCredentials\") {\r\n throw new AuthenticationError(\"No auth configured — set auth in DuprClientOptions or call setBearerToken()\", 401);\r\n }\r\n\r\n if (this.token && Date.now() < this.tokenExpiresAt) {\r\n return this.token;\r\n }\r\n\r\n const { clientKey, clientSecret } = this.config.auth;\r\n const encoded = Buffer.from(`${clientKey}:${clientSecret}`).toString(\"base64\");\r\n const url = `${this.config.baseUrl}/auth/${this.config.version}/token`;\r\n\r\n const start = Date.now();\r\n const res = await this.config.customFetch(url, {\r\n method: \"POST\",\r\n headers: {\r\n \"x-authorization\": encoded,\r\n \"User-Agent\": this.config.userAgent,\r\n },\r\n signal: AbortSignal.timeout(this.config.timeoutMs),\r\n });\r\n\r\n this.config.onResponse?.({ status: res.status, url, durationMs: Date.now() - start });\r\n\r\n if (!res.ok) throw await buildError(res);\r\n\r\n const body = await res.json() as { token?: string; accessToken?: string; expiresIn?: number };\r\n this.token = body.token ?? body.accessToken ?? null;\r\n if (!this.token) throw new AuthenticationError(\"Token response contained no token\", 401);\r\n\r\n const ttlSec = body.expiresIn ?? 3600;\r\n this.tokenExpiresAt = Date.now() + (ttlSec - 60) * 1000;\r\n return this.token;\r\n }\r\n\r\n async get<T>(path: string, init?: RequestInit): Promise<T> {\r\n return this.request<T>(\"GET\", path, init);\r\n }\r\n\r\n async post<T>(path: string, body?: unknown, init?: RequestInit): Promise<T> {\r\n const extra: RequestInit = { headers: { \"Content-Type\": \"application/json\", ...(init?.headers ?? {}) } };\r\n if (body !== undefined) extra.body = JSON.stringify(body);\r\n return this.request<T>(\"POST\", path, { ...init, ...extra });\r\n }\r\n\r\n async delete<T>(path: string, body?: unknown, init?: RequestInit): Promise<T> {\r\n const extra: RequestInit = { headers: { \"Content-Type\": \"application/json\", ...(init?.headers ?? {}) } };\r\n if (body !== undefined) extra.body = JSON.stringify(body);\r\n return this.request<T>(\"DELETE\", path, { ...init, ...extra });\r\n }\r\n\r\n async request<T>(method: string, path: string, init?: RequestInit): Promise<T> {\r\n const retryCfg = this.config.retry;\r\n const maxAttempts = retryCfg === false ? 1 : retryCfg.maxRetries + 1;\r\n\r\n let lastErr: unknown;\r\n\r\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\r\n try {\r\n return await this.rawRequest<T>(method, path, init);\r\n } catch (err) {\r\n lastErr = err;\r\n\r\n if (attempt >= maxAttempts - 1) break;\r\n if (!isRetryable(err)) break;\r\n if (retryCfg === false) break;\r\n\r\n let delay: number;\r\n if (err instanceof RateLimitError) {\r\n // Honor Retry-After header (value in seconds)\r\n const retryAfterSec =\r\n err.details !== null &&\r\n typeof err.details === \"object\" &&\r\n \"retryAfterSeconds\" in (err.details as object)\r\n ? Number((err.details as { retryAfterSeconds: unknown }).retryAfterSeconds)\r\n : NaN;\r\n delay = Number.isFinite(retryAfterSec) && retryAfterSec > 0\r\n ? retryAfterSec * 1000\r\n : retryDelayMs(attempt, retryCfg.baseDelayMs, retryCfg.maxDelayMs);\r\n } else {\r\n delay = retryDelayMs(attempt, retryCfg.baseDelayMs, retryCfg.maxDelayMs);\r\n }\r\n\r\n await sleep(delay);\r\n }\r\n }\r\n\r\n throw lastErr;\r\n }\r\n\r\n private async rawRequest<T>(method: string, path: string, init?: RequestInit): Promise<T> {\r\n const token = await this.getBearerToken();\r\n const url = `${this.config.baseUrl}${path}`;\r\n\r\n const headers: Record<string, string> = {\r\n Authorization: `Bearer ${token}`,\r\n \"User-Agent\": this.config.userAgent,\r\n ...(init?.headers as Record<string, string> | undefined ?? {}),\r\n };\r\n\r\n this.config.onRequest?.({ method, url, headers });\r\n\r\n const start = Date.now();\r\n const res = await this.config.customFetch(url, {\r\n method,\r\n ...init,\r\n headers,\r\n signal: AbortSignal.timeout(this.config.timeoutMs),\r\n });\r\n\r\n this.config.onResponse?.({ status: res.status, url, durationMs: Date.now() - start });\r\n\r\n if (!res.ok) {\r\n const err = await buildError(res);\r\n // Attach Retry-After from the response header so the retry loop can read it\r\n if (err instanceof RateLimitError) {\r\n const retryAfter = res.headers.get(\"Retry-After\");\r\n if (retryAfter) {\r\n (err as RateLimitError & { details: unknown }).details =\r\n typeof err.details === \"object\" && err.details !== null\r\n ? { ...err.details as object, retryAfterSeconds: Number(retryAfter) }\r\n : { retryAfterSeconds: Number(retryAfter) };\r\n }\r\n }\r\n throw err;\r\n }\r\n\r\n // Some endpoints return 204 No Content\r\n if (res.status === 204 || res.headers.get(\"content-length\") === \"0\") {\r\n return undefined as T;\r\n }\r\n\r\n return res.json() as Promise<T>;\r\n }\r\n}\r\n","import { HttpClient } from \"./http.js\";\r\nimport { ResolvedConfig } from \"./config.js\";\r\nimport { AuthenticationError } from \"./errors.js\";\r\nimport { TokenResponse } from \"./types.js\";\r\n\r\nexport interface AuthCodeTokenResponse extends TokenResponse {\r\n refresh_token?: string;\r\n token_type?: string;\r\n scope?: string;\r\n}\r\n\r\nexport interface AuthorizationUrlParams {\r\n /** Your OAuth redirect URI, must match what is registered with DUPR. */\r\n redirectUri: string;\r\n /** OAuth scopes to request (e.g. [\"user.read\"]). Defaults to empty. */\r\n scopes?: string[];\r\n /** Opaque value passed through the flow to prevent CSRF. Recommended. */\r\n state?: string;\r\n}\r\n\r\nexport class AuthModule {\r\n constructor(\r\n private readonly http: HttpClient,\r\n private readonly config: ResolvedConfig,\r\n ) {}\r\n\r\n /**\r\n * Explicitly request a new access token using client credentials.\r\n * Normally you don't need to call this — the HTTP client handles token refresh automatically.\r\n */\r\n async getToken(): Promise<TokenResponse> {\r\n if (this.config.auth.type !== \"clientCredentials\") {\r\n throw new AuthenticationError(\"getToken() requires clientCredentials auth mode\", 401);\r\n }\r\n const { clientKey, clientSecret } = this.config.auth;\r\n const encoded = Buffer.from(`${clientKey}:${clientSecret}`).toString(\"base64\");\r\n const url = `${this.config.baseUrl}/auth/${this.config.version}/token`;\r\n\r\n const res = await this.config.customFetch(url, {\r\n method: \"POST\",\r\n headers: {\r\n \"x-authorization\": encoded,\r\n \"User-Agent\": this.config.userAgent,\r\n },\r\n signal: AbortSignal.timeout(this.config.timeoutMs),\r\n });\r\n\r\n if (!res.ok) {\r\n const body = await res.json().catch(() => undefined) as Record<string, unknown> | undefined;\r\n throw new AuthenticationError(\r\n (body?.[\"message\"] as string | undefined) ?? `Auth failed: ${res.status}`,\r\n res.status,\r\n body,\r\n );\r\n }\r\n\r\n return res.json() as Promise<TokenResponse>;\r\n }\r\n\r\n // ── Authorization Code Flow ───────────────────────────────────────────────\r\n //\r\n // Use this flow to let end-users authorise your app to act on their behalf\r\n // (e.g. the \"Connect DUPR\" button). The user is redirected to DUPR's login\r\n // page, then back to your redirectUri with an authorization code.\r\n //\r\n // NOTE: This requires a DUPR OAuth application with an authorization endpoint\r\n // separate from the Partner API client credentials. Confirm the exact\r\n // authorization URL with DUPR support.\r\n //\r\n // Typical flow:\r\n // 1. client.auth.getAuthorizationUrl({ redirectUri, state }) → redirect user\r\n // 2. User approves → DUPR calls back to redirectUri?code=xxx&state=yyy\r\n // 3. client.auth.exchangeCode({ code, redirectUri }) → tokens\r\n // 4. Store access_token + refresh_token; call client.setBearerToken(access_token)\r\n // 5. When access_token expires: client.auth.refreshToken(refresh_token)\r\n\r\n /**\r\n * Build the DUPR authorization URL to redirect the user to for login.\r\n * The `authorizationUrl` config option must be set (see above note).\r\n */\r\n getAuthorizationUrl(params: AuthorizationUrlParams): string {\r\n const authUrl = (this.config as ResolvedConfig & { authorizationUrl?: string }).authorizationUrl;\r\n if (!authUrl) {\r\n throw new Error(\r\n \"authorizationUrl is not configured. Pass it in DuprClientOptions to use the Authorization Code flow.\",\r\n );\r\n }\r\n const url = new URL(authUrl);\r\n const clientId = this.config.auth.type === \"clientCredentials\" ? this.config.auth.clientKey : \"\";\r\n url.searchParams.set(\"response_type\", \"code\");\r\n url.searchParams.set(\"client_id\", clientId);\r\n url.searchParams.set(\"redirect_uri\", params.redirectUri);\r\n if (params.scopes?.length) url.searchParams.set(\"scope\", params.scopes.join(\" \"));\r\n if (params.state) url.searchParams.set(\"state\", params.state);\r\n return url.toString();\r\n }\r\n\r\n /**\r\n * Exchange an authorization code (from the OAuth callback) for access + refresh tokens.\r\n * Uses `POST /auth/{version}/token` with `grant_type=authorization_code`.\r\n */\r\n async exchangeCode(params: {\r\n code: string;\r\n redirectUri: string;\r\n }): Promise<AuthCodeTokenResponse> {\r\n if (this.config.auth.type !== \"clientCredentials\") {\r\n throw new AuthenticationError(\"exchangeCode() requires clientCredentials auth configured with clientKey/clientSecret\", 401);\r\n }\r\n const { clientKey, clientSecret } = this.config.auth;\r\n const url = `${this.config.baseUrl}/auth/${this.config.version}/token`;\r\n const body = new URLSearchParams({\r\n grant_type: \"authorization_code\",\r\n code: params.code,\r\n redirect_uri: params.redirectUri,\r\n client_id: clientKey,\r\n client_secret: clientSecret,\r\n });\r\n\r\n const res = await this.config.customFetch(url, {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/x-www-form-urlencoded\",\r\n \"User-Agent\": this.config.userAgent,\r\n },\r\n body: body.toString(),\r\n signal: AbortSignal.timeout(this.config.timeoutMs),\r\n });\r\n\r\n if (!res.ok) {\r\n const errBody = await res.json().catch(() => undefined) as Record<string, unknown> | undefined;\r\n throw new AuthenticationError(\r\n (errBody?.[\"message\"] as string | undefined) ?? `Code exchange failed: ${res.status}`,\r\n res.status,\r\n errBody,\r\n );\r\n }\r\n\r\n return res.json() as Promise<AuthCodeTokenResponse>;\r\n }\r\n\r\n /**\r\n * Obtain a new access token using a refresh token from a previous Authorization Code flow.\r\n * Uses `POST /auth/{version}/token` with `grant_type=refresh_token`.\r\n */\r\n async refreshToken(refreshToken: string): Promise<AuthCodeTokenResponse> {\r\n if (this.config.auth.type !== \"clientCredentials\") {\r\n throw new AuthenticationError(\"refreshToken() requires clientCredentials auth configured\", 401);\r\n }\r\n const { clientKey, clientSecret } = this.config.auth;\r\n const url = `${this.config.baseUrl}/auth/${this.config.version}/token`;\r\n const body = new URLSearchParams({\r\n grant_type: \"refresh_token\",\r\n refresh_token: refreshToken,\r\n client_id: clientKey,\r\n client_secret: clientSecret,\r\n });\r\n\r\n const res = await this.config.customFetch(url, {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/x-www-form-urlencoded\",\r\n \"User-Agent\": this.config.userAgent,\r\n },\r\n body: body.toString(),\r\n signal: AbortSignal.timeout(this.config.timeoutMs),\r\n });\r\n\r\n if (!res.ok) {\r\n const errBody = await res.json().catch(() => undefined) as Record<string, unknown> | undefined;\r\n throw new AuthenticationError(\r\n (errBody?.[\"message\"] as string | undefined) ?? `Token refresh failed: ${res.status}`,\r\n res.status,\r\n errBody,\r\n );\r\n }\r\n\r\n return res.json() as Promise<AuthCodeTokenResponse>;\r\n }\r\n}\r\n","import { HttpClient } from \"../http.js\";\r\nimport { ResolvedConfig } from \"../config.js\";\r\nimport {\r\n ApiWrapper,\r\n ClubMembershipResponse,\r\n CreateProvisionalRatingRequest,\r\n DeleteProvisionalRatingRequest,\r\n ExtendedUserInfo,\r\n ExternalBatchUserDetailRequest,\r\n ExternalInviteRequest,\r\n ExternalSearchRequest,\r\n GetProvisionalRatingRequest,\r\n GrantExternalSubscriptionRequest,\r\n UpdateProvisionalRatingRequest,\r\n UserInfo,\r\n} from \"../types.js\";\r\n\r\nexport class UsersModule {\r\n constructor(\r\n private readonly http: HttpClient,\r\n private readonly cfg: ResolvedConfig,\r\n ) {}\r\n\r\n /** GET /user/{version}/{id} — basic player profile */\r\n getUser(duprId: string): Promise<ApiWrapper<UserInfo>> {\r\n return this.http.get(`/user/${this.cfg.version}/${duprId}`);\r\n }\r\n\r\n /** GET /user/{version}/{id}/details — extended profile (requires USER_EMAIL::VIEW permission) */\r\n getExtendedUser(duprId: string): Promise<ApiWrapper<ExtendedUserInfo>> {\r\n return this.http.get(`/user/${this.cfg.version}/${duprId}/details`);\r\n }\r\n\r\n /** GET /user/{version}/{id}/clubs — club memberships for a player */\r\n getClubMemberships(duprId: string): Promise<ClubMembershipResponse> {\r\n return this.http.get(`/user/${this.cfg.version}/${duprId}/clubs`);\r\n }\r\n\r\n /** POST /user/{version}/search — full-text player search with optional filters */\r\n search(req: ExternalSearchRequest): Promise<ApiWrapper<UserInfo[]>> {\r\n return this.http.post(`/user/${this.cfg.version}/search`, req);\r\n }\r\n\r\n /** POST /user/{version}/batch — fetch multiple players by DUPR ID in one request */\r\n getBatch(req: ExternalBatchUserDetailRequest): Promise<ApiWrapper<UserInfo[]>> {\r\n return this.http.post(`/user/${this.cfg.version}/batch`, req);\r\n }\r\n\r\n /** POST /user/{version}/invite — pre-generate a DUPR ID and send an invite email */\r\n invite(req: ExternalInviteRequest): Promise<ApiWrapper<{ duprId: string }>> {\r\n return this.http.post(`/user/${this.cfg.version}/invite`, req);\r\n }\r\n\r\n /** POST /user/{version}/subscription/grants — grant a subscription to a user */\r\n grantSubscription(req: GrantExternalSubscriptionRequest): Promise<ApiWrapper> {\r\n return this.http.post(`/user/${this.cfg.version}/subscription/grants`, req);\r\n }\r\n\r\n // ── Provisional ratings ──────────────────────────────────────\r\n\r\n /** POST /user/{version}/provisional_rating — get provisional ratings for a player */\r\n getProvisionalRating(req: GetProvisionalRatingRequest): Promise<ApiWrapper> {\r\n return this.http.post(`/user/${this.cfg.version}/provisional_rating`, req);\r\n }\r\n\r\n /** POST /user/{version}/provisional_rating/create */\r\n createProvisionalRating(req: CreateProvisionalRatingRequest): Promise<ApiWrapper> {\r\n return this.http.post(`/user/${this.cfg.version}/provisional_rating/create`, req);\r\n }\r\n\r\n /** POST /user/{version}/provisional_rating/update */\r\n updateProvisionalRating(req: UpdateProvisionalRatingRequest): Promise<ApiWrapper> {\r\n return this.http.post(`/user/${this.cfg.version}/provisional_rating/update`, req);\r\n }\r\n\r\n /** DELETE /user/{version}/provisional_rating/delete */\r\n deleteProvisionalRating(req: DeleteProvisionalRatingRequest): Promise<ApiWrapper> {\r\n return this.http.delete(`/user/${this.cfg.version}/provisional_rating/delete`, req);\r\n }\r\n}\r\n","import { HttpClient } from \"../http.js\";\r\nimport { ResolvedConfig } from \"../config.js\";\r\nimport { ApiWrapper } from \"../types.js\";\r\n\r\nexport interface GetDuprIdByEmailRequest {\r\n email: string;\r\n}\r\n\r\nexport interface DuprIdByEmailResponse {\r\n duprId?: string;\r\n}\r\n\r\nexport class PlayersModule {\r\n constructor(\r\n private readonly http: HttpClient,\r\n private readonly cfg: ResolvedConfig,\r\n ) {}\r\n\r\n /** POST /{version}/player/duprid-by-email — resolve a DUPR ID from an email address */\r\n getDuprIdByEmail(req: GetDuprIdByEmailRequest): Promise<ApiWrapper<DuprIdByEmailResponse>> {\r\n return this.http.post(`/${this.cfg.version}/player/duprid-by-email`, req);\r\n }\r\n}\r\n","import { HttpClient } from \"../http.js\";\r\nimport { ResolvedConfig } from \"../config.js\";\r\nimport { ApiWrapper, PlayerRatingSubscribeRequest } from \"../types.js\";\r\n\r\nexport interface PlayerRatingHistoryRequest {\r\n duprId: string;\r\n offset?: number;\r\n limit?: number;\r\n}\r\n\r\nexport interface PlayerRatingHistoryEntry {\r\n date?: string;\r\n singlesRating?: number;\r\n doublesRating?: number;\r\n}\r\n\r\nexport class PlayerRatingModule {\r\n constructor(\r\n private readonly http: HttpClient,\r\n private readonly cfg: ResolvedConfig,\r\n ) {}\r\n\r\n /** POST /history — get rating history for a player */\r\n getHistory(req: PlayerRatingHistoryRequest): Promise<ApiWrapper<PlayerRatingHistoryEntry[]>> {\r\n return this.http.post(`/history`, req);\r\n }\r\n\r\n /** GET /{version}/subscribe/rating-changes — list currently subscribed DUPR IDs */\r\n getSubscriptions(): Promise<ApiWrapper<{ duprIds: string[] }>> {\r\n return this.http.get(`/${this.cfg.version}/subscribe/rating-changes`);\r\n }\r\n\r\n /** POST /{version}/subscribe/rating-changes — subscribe to rating-change events for a list of players */\r\n subscribe(req: PlayerRatingSubscribeRequest): Promise<ApiWrapper> {\r\n return this.http.post(`/${this.cfg.version}/subscribe/rating-changes`, req);\r\n }\r\n\r\n /** DELETE /{version}/subscribe/rating-changes — unsubscribe from rating-change events */\r\n unsubscribe(req: PlayerRatingSubscribeRequest): Promise<ApiWrapper> {\r\n return this.http.delete(`/${this.cfg.version}/subscribe/rating-changes`, req);\r\n }\r\n}\r\n","import { HttpClient } from \"../http.js\";\r\nimport { ResolvedConfig } from \"../config.js\";\r\nimport {\r\n ApiWrapper,\r\n ExternalDeleteMatchRequest,\r\n ExternalMatchRequest,\r\n ExternalMatchSearchRequest,\r\n ExternalUpdateMatchRequest,\r\n MatchResponse,\r\n} from \"../types.js\";\r\n\r\nexport interface AnnotateMatchRequest {\r\n matchId: string;\r\n annotation: Record<string, unknown>;\r\n}\r\n\r\nexport class MatchesModule {\r\n constructor(\r\n private readonly http: HttpClient,\r\n private readonly cfg: ResolvedConfig,\r\n ) {}\r\n\r\n /** GET /match/{version}/{id} — view a single match */\r\n get(matchId: string): Promise<ApiWrapper<MatchResponse>> {\r\n return this.http.get(`/match/${this.cfg.version}/${matchId}`);\r\n }\r\n\r\n /** POST /match/{version}/create — submit a new match result */\r\n create(match: ExternalMatchRequest): Promise<ApiWrapper<MatchResponse>> {\r\n return this.http.post(`/match/${this.cfg.version}/create`, match);\r\n }\r\n\r\n /** POST /match/{version}/batch — submit multiple match results in one call */\r\n createBulk(matches: ExternalMatchRequest[]): Promise<ApiWrapper<MatchResponse[]>> {\r\n return this.http.post(`/match/${this.cfg.version}/batch`, matches);\r\n }\r\n\r\n /** POST /match/{version}/update — update an existing match */\r\n update(req: ExternalUpdateMatchRequest): Promise<ApiWrapper<MatchResponse>> {\r\n return this.http.post(`/match/${this.cfg.version}/update`, req);\r\n }\r\n\r\n /** DELETE /match/{version}/delete — delete a match */\r\n delete(req: ExternalDeleteMatchRequest): Promise<ApiWrapper> {\r\n return this.http.delete(`/match/${this.cfg.version}/delete`, req);\r\n }\r\n\r\n /** POST /match/{version}/annotate — attach vendor-specific metadata to a match */\r\n annotate(req: AnnotateMatchRequest): Promise<ApiWrapper> {\r\n return this.http.post(`/match/${this.cfg.version}/annotate`, req);\r\n }\r\n\r\n /** DELETE /match/{version}/annotate/{matchId} — remove a match annotation */\r\n deleteAnnotation(matchId: string): Promise<ApiWrapper> {\r\n return this.http.delete(`/match/${this.cfg.version}/annotate/${matchId}`);\r\n }\r\n\r\n /** POST /match/history/search — search a player's match history */\r\n searchHistory(req: ExternalMatchSearchRequest): Promise<ApiWrapper<MatchResponse[]>> {\r\n return this.http.post(`/match/history/search`, req);\r\n }\r\n}\r\n","import { HttpClient } from \"../http.js\";\r\nimport { ResolvedConfig } from \"../config.js\";\r\nimport {\r\n ApiWrapper,\r\n ExternalClubMemberRequest,\r\n ExternalClubMatchSearchRequest,\r\n MatchResponse,\r\n UserInfo,\r\n} from \"../types.js\";\r\n\r\nexport class ClubsModule {\r\n constructor(\r\n private readonly http: HttpClient,\r\n private readonly cfg: ResolvedConfig,\r\n ) {}\r\n\r\n /** POST /club/{version}/members — get ratings for all members of a club */\r\n membersRating(req: ExternalClubMemberRequest): Promise<ApiWrapper<UserInfo[]>> {\r\n return this.http.post(`/club/${this.cfg.version}/members`, req);\r\n }\r\n\r\n /** POST /club/{version}/match/search — search matches associated with a club */\r\n searchMatches(req: ExternalClubMatchSearchRequest): Promise<ApiWrapper<MatchResponse[]>> {\r\n return this.http.post(`/club/${this.cfg.version}/match/search`, req);\r\n }\r\n}\r\n","import { HttpClient } from \"../http.js\";\r\nimport { ResolvedConfig } from \"../config.js\";\r\nimport {\r\n ApiWrapper,\r\n CreateEventRequestV1,\r\n CreateEventResponseV1,\r\n DeleteEventRequestV1,\r\n DeleteEventResponseV1,\r\n GetEventRequestV1,\r\n GetEventResponseV1,\r\n UpdateEventRequestV1,\r\n UpdateEventResponseV1,\r\n} from \"../types.js\";\r\n\r\nexport class EventsModule {\r\n constructor(\r\n private readonly http: HttpClient,\r\n private readonly cfg: ResolvedConfig,\r\n ) {}\r\n\r\n /** POST /events/{version}/create */\r\n create(req: CreateEventRequestV1): Promise<ApiWrapper<CreateEventResponseV1>> {\r\n return this.http.post(`/events/${this.cfg.version}/create`, req);\r\n }\r\n\r\n /** GET /events/{version}/get */\r\n get(req: GetEventRequestV1): Promise<ApiWrapper<GetEventResponseV1>> {\r\n return this.http.post(`/events/${this.cfg.version}/get`, req);\r\n }\r\n\r\n /** POST /events/{version}/update */\r\n update(req: UpdateEventRequestV1): Promise<ApiWrapper<UpdateEventResponseV1>> {\r\n return this.http.post(`/events/${this.cfg.version}/update`, req);\r\n }\r\n\r\n /** POST /events/{version}/delete */\r\n delete(req: DeleteEventRequestV1): Promise<ApiWrapper<DeleteEventResponseV1>> {\r\n return this.http.post(`/events/${this.cfg.version}/delete`, req);\r\n }\r\n}\r\n","import { HttpClient } from \"../http.js\";\r\nimport { ResolvedConfig } from \"../config.js\";\r\nimport { ApiWrapper, ClientHookRequest, UserWebhookRequest, WebhookSchema } from \"../types.js\";\r\n\r\nexport class WebhooksModule {\r\n constructor(\r\n private readonly http: HttpClient,\r\n private readonly cfg: ResolvedConfig,\r\n ) {}\r\n\r\n /** POST /{version}/webhook — register a webhook endpoint */\r\n register(req: ClientHookRequest): Promise<ApiWrapper> {\r\n return this.http.post(`/${this.cfg.version}/webhook`, req);\r\n }\r\n\r\n /** GET /{version}/topic — list all available webhook topics */\r\n getTopics(): Promise<ApiWrapper<string[]>> {\r\n return this.http.get(`/${this.cfg.version}/topic`);\r\n }\r\n\r\n /** GET /{version}/webhook/schema — list available webhook schemas */\r\n listSchemas(): Promise<ApiWrapper<WebhookSchema[]>> {\r\n return this.http.get(`/${this.cfg.version}/webhook/schema`);\r\n }\r\n\r\n /** GET /{version}/webhook/schema/{topic} — get the JSON schema for a specific topic */\r\n getSchema(topic: string): Promise<ApiWrapper<WebhookSchema>> {\r\n return this.http.get(`/${this.cfg.version}/webhook/schema/${topic}`);\r\n }\r\n\r\n /** POST /user/{version}/subscribe/webhook-event — subscribe specific users to a webhook topic */\r\n subscribeUsers(req: UserWebhookRequest): Promise<ApiWrapper> {\r\n return this.http.post(`/user/${this.cfg.version}/subscribe/webhook-event`, req);\r\n }\r\n\r\n /** DELETE /user/{version}/subscribe/webhook-event — unsubscribe specific users from a webhook topic */\r\n unsubscribeUsers(req: UserWebhookRequest): Promise<ApiWrapper> {\r\n return this.http.delete(`/user/${this.cfg.version}/subscribe/webhook-event`, req);\r\n }\r\n}\r\n","import { DuprClientOptions, ResolvedConfig, resolveConfig } from \"./config.js\";\r\nimport { HttpClient } from \"./http.js\";\r\nimport { AuthModule } from \"./auth.js\";\r\nimport { UsersModule } from \"./resources/users.js\";\r\nimport { PlayersModule } from \"./resources/players.js\";\r\nimport { PlayerRatingModule } from \"./resources/playerRating.js\";\r\nimport { MatchesModule } from \"./resources/matches.js\";\r\nimport { ClubsModule } from \"./resources/clubs.js\";\r\nimport { EventsModule } from \"./resources/events.js\";\r\nimport { WebhooksModule } from \"./resources/webhooks.js\";\r\n\r\nexport class DuprClient {\r\n readonly config: ResolvedConfig;\r\n readonly auth: AuthModule;\r\n readonly users: UsersModule;\r\n readonly players: PlayersModule;\r\n readonly playerRating: PlayerRatingModule;\r\n readonly matches: MatchesModule;\r\n readonly clubs: ClubsModule;\r\n readonly events: EventsModule;\r\n readonly webhooks: WebhooksModule;\r\n\r\n constructor(opts: DuprClientOptions = {}) {\r\n this.config = resolveConfig(opts);\r\n const http = new HttpClient(this.config);\r\n this.auth = new AuthModule(http, this.config);\r\n this.users = new UsersModule(http, this.config);\r\n this.players = new PlayersModule(http, this.config);\r\n this.playerRating = new PlayerRatingModule(http, this.config);\r\n this.matches = new MatchesModule(http, this.config);\r\n this.clubs = new ClubsModule(http, this.config);\r\n this.events = new EventsModule(http, this.config);\r\n this.webhooks = new WebhooksModule(http, this.config);\r\n }\r\n\r\n /** Override the bearer token at runtime — useful when your backend handles auth separately. */\r\n setBearerToken(token: string): void {\r\n this.config.overrideBearerToken = token;\r\n }\r\n\r\n /** Clear the runtime bearer token override and fall back to configured auth. */\r\n clearBearerToken(): void {\r\n delete this.config.overrideBearerToken;\r\n }\r\n}\r\n"]}
|
package/dist/index.d.cts
DELETED
|
@@ -1,516 +0,0 @@
|
|
|
1
|
-
type AuthMode = {
|
|
2
|
-
type: "clientCredentials";
|
|
3
|
-
clientKey: string;
|
|
4
|
-
clientSecret: string;
|
|
5
|
-
} | {
|
|
6
|
-
type: "staticBearer";
|
|
7
|
-
bearerToken: string;
|
|
8
|
-
} | {
|
|
9
|
-
type: "none";
|
|
10
|
-
};
|
|
11
|
-
interface RequestInfo {
|
|
12
|
-
method: string;
|
|
13
|
-
url: string;
|
|
14
|
-
headers: Record<string, string>;
|
|
15
|
-
}
|
|
16
|
-
interface ResponseInfo {
|
|
17
|
-
status: number;
|
|
18
|
-
url: string;
|
|
19
|
-
durationMs: number;
|
|
20
|
-
}
|
|
21
|
-
interface RetryOptions {
|
|
22
|
-
/** Max number of retry attempts after the initial failure. @default 3 */
|
|
23
|
-
maxRetries?: number;
|
|
24
|
-
/** Base delay in ms before the first retry. Doubles on each attempt. @default 1_000 */
|
|
25
|
-
baseDelayMs?: number;
|
|
26
|
-
/** Max delay cap in ms (prevents infinite backoff). @default 30_000 */
|
|
27
|
-
maxDelayMs?: number;
|
|
28
|
-
}
|
|
29
|
-
interface DuprClientOptions {
|
|
30
|
-
/** @default "https://uat.mydupr.com/api" */
|
|
31
|
-
baseUrl?: string;
|
|
32
|
-
/** API version prefix used in all paths. @default "v1.0" */
|
|
33
|
-
version?: string;
|
|
34
|
-
/** Request timeout in milliseconds. @default 30_000 */
|
|
35
|
-
timeoutMs?: number;
|
|
36
|
-
auth?: AuthMode;
|
|
37
|
-
/** Custom User-Agent header. */
|
|
38
|
-
userAgent?: string;
|
|
39
|
-
/** Inject a custom fetch implementation (useful for testing or polyfilling). */
|
|
40
|
-
customFetch?: typeof fetch;
|
|
41
|
-
/** Called before every request. Useful for logging or tracing. */
|
|
42
|
-
onRequest?: (info: RequestInfo) => void;
|
|
43
|
-
/** Called after every response (including errors). */
|
|
44
|
-
onResponse?: (info: ResponseInfo) => void;
|
|
45
|
-
/** Retry behaviour for transient errors (5xx, network failures, 429). Pass `false` to disable. */
|
|
46
|
-
retry?: RetryOptions | false;
|
|
47
|
-
}
|
|
48
|
-
interface ResolvedRetryOptions {
|
|
49
|
-
maxRetries: number;
|
|
50
|
-
baseDelayMs: number;
|
|
51
|
-
maxDelayMs: number;
|
|
52
|
-
}
|
|
53
|
-
interface ResolvedConfig {
|
|
54
|
-
baseUrl: string;
|
|
55
|
-
version: string;
|
|
56
|
-
timeoutMs: number;
|
|
57
|
-
auth: AuthMode;
|
|
58
|
-
userAgent: string;
|
|
59
|
-
customFetch: typeof fetch;
|
|
60
|
-
retry: ResolvedRetryOptions | false;
|
|
61
|
-
onRequest?: (info: RequestInfo) => void;
|
|
62
|
-
onResponse?: (info: ResponseInfo) => void;
|
|
63
|
-
/** Runtime override for the bearer token — set via `client.setBearerToken()`. */
|
|
64
|
-
overrideBearerToken?: string;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
declare class HttpClient {
|
|
68
|
-
private readonly config;
|
|
69
|
-
private token;
|
|
70
|
-
private tokenExpiresAt;
|
|
71
|
-
constructor(config: ResolvedConfig);
|
|
72
|
-
private getBearerToken;
|
|
73
|
-
get<T>(path: string, init?: RequestInit): Promise<T>;
|
|
74
|
-
post<T>(path: string, body?: unknown, init?: RequestInit): Promise<T>;
|
|
75
|
-
delete<T>(path: string, body?: unknown, init?: RequestInit): Promise<T>;
|
|
76
|
-
request<T>(method: string, path: string, init?: RequestInit): Promise<T>;
|
|
77
|
-
private rawRequest;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
type MatchFormat = "SINGLES" | "DOUBLES";
|
|
81
|
-
type MatchSource = "PARTNER" | "CLUB";
|
|
82
|
-
type Gender = "MALE" | "FEMALE";
|
|
83
|
-
type RatingType = "SINGLES" | "DOUBLES";
|
|
84
|
-
type WebhookTopic = "RATING";
|
|
85
|
-
type ApiStatus = "SUCCESS" | "FAILURE";
|
|
86
|
-
interface ApiWrapper<T = unknown> {
|
|
87
|
-
status: ApiStatus;
|
|
88
|
-
message?: string;
|
|
89
|
-
result?: T;
|
|
90
|
-
}
|
|
91
|
-
interface TokenResponse {
|
|
92
|
-
token?: string;
|
|
93
|
-
accessToken?: string;
|
|
94
|
-
expiresIn?: number;
|
|
95
|
-
}
|
|
96
|
-
interface UserInfo {
|
|
97
|
-
duprId: string;
|
|
98
|
-
fullName: string;
|
|
99
|
-
singlesRating?: number;
|
|
100
|
-
doublesRating?: number;
|
|
101
|
-
singlesProvisional?: boolean;
|
|
102
|
-
doublesProvisional?: boolean;
|
|
103
|
-
}
|
|
104
|
-
interface ExtendedUserInfo extends UserInfo {
|
|
105
|
-
email?: string;
|
|
106
|
-
}
|
|
107
|
-
interface ClubMembership {
|
|
108
|
-
clubId: string;
|
|
109
|
-
clubName: string;
|
|
110
|
-
role: string;
|
|
111
|
-
}
|
|
112
|
-
interface ClubMembershipResult {
|
|
113
|
-
clubs: ClubMembership[];
|
|
114
|
-
}
|
|
115
|
-
type ClubMembershipResponse = ApiWrapper<ClubMembershipResult>;
|
|
116
|
-
interface ExternalSearchFilter {
|
|
117
|
-
gender?: Gender;
|
|
118
|
-
location?: ExternalFilterLocation;
|
|
119
|
-
rating?: ExternalRatingFilter;
|
|
120
|
-
age?: ExternalAgeRangeFilter;
|
|
121
|
-
}
|
|
122
|
-
interface ExternalFilterLocation {
|
|
123
|
-
lat: number;
|
|
124
|
-
lng: number;
|
|
125
|
-
address?: string;
|
|
126
|
-
radiusInMeters?: number;
|
|
127
|
-
}
|
|
128
|
-
interface ExternalRatingFilter {
|
|
129
|
-
min?: number;
|
|
130
|
-
max?: number;
|
|
131
|
-
type?: RatingType;
|
|
132
|
-
reliable?: boolean;
|
|
133
|
-
}
|
|
134
|
-
interface ExternalAgeRangeFilter {
|
|
135
|
-
min?: number;
|
|
136
|
-
max?: number;
|
|
137
|
-
}
|
|
138
|
-
interface ExternalSearchRequest {
|
|
139
|
-
query: string;
|
|
140
|
-
offset: number;
|
|
141
|
-
limit: number;
|
|
142
|
-
filters?: ExternalSearchFilter;
|
|
143
|
-
}
|
|
144
|
-
interface ExternalBatchUserDetailRequest {
|
|
145
|
-
duprIds: string[];
|
|
146
|
-
}
|
|
147
|
-
interface ExternalInviteRequest {
|
|
148
|
-
firstName: string;
|
|
149
|
-
lastName: string;
|
|
150
|
-
email: string;
|
|
151
|
-
}
|
|
152
|
-
interface RatingCoach {
|
|
153
|
-
id: string;
|
|
154
|
-
metadata: Record<string, string>;
|
|
155
|
-
}
|
|
156
|
-
interface GetProvisionalRatingRequest {
|
|
157
|
-
duprId: string;
|
|
158
|
-
}
|
|
159
|
-
interface CreateProvisionalRatingRequest {
|
|
160
|
-
duprId: string;
|
|
161
|
-
provisionalSinglesRating?: number;
|
|
162
|
-
provisionalDoublesRating?: number;
|
|
163
|
-
coach?: RatingCoach;
|
|
164
|
-
}
|
|
165
|
-
interface UpdateProvisionalRatingRequest {
|
|
166
|
-
duprId: string;
|
|
167
|
-
provisionalSinglesRating?: number;
|
|
168
|
-
provisionalDoublesRating?: number;
|
|
169
|
-
}
|
|
170
|
-
interface DeleteProvisionalRatingRequest {
|
|
171
|
-
duprId: string;
|
|
172
|
-
}
|
|
173
|
-
interface ExternalMatchPlayer {
|
|
174
|
-
duprId: string;
|
|
175
|
-
}
|
|
176
|
-
interface ExternalMatchTeam {
|
|
177
|
-
/** 1 player for SINGLES, 2 for DOUBLES */
|
|
178
|
-
players: ExternalMatchPlayer[];
|
|
179
|
-
/** Scores per game, aligned with the opposing team's scores array */
|
|
180
|
-
scores: number[];
|
|
181
|
-
}
|
|
182
|
-
interface ExternalMatchRequest {
|
|
183
|
-
/** Your universally unique identifier — must not be reused across matches */
|
|
184
|
-
identifier: string;
|
|
185
|
-
/** yyyy-MM-dd */
|
|
186
|
-
matchDate: string;
|
|
187
|
-
matchFormat: MatchFormat;
|
|
188
|
-
teams: [ExternalMatchTeam, ExternalMatchTeam];
|
|
189
|
-
source: MatchSource;
|
|
190
|
-
eventId?: number;
|
|
191
|
-
clubId?: number;
|
|
192
|
-
}
|
|
193
|
-
interface ExternalUpdateMatchRequest {
|
|
194
|
-
matchId: string;
|
|
195
|
-
matchDate?: string;
|
|
196
|
-
teams?: [ExternalMatchTeam, ExternalMatchTeam];
|
|
197
|
-
}
|
|
198
|
-
interface ExternalDeleteMatchRequest {
|
|
199
|
-
matchCode: string;
|
|
200
|
-
identifier: string;
|
|
201
|
-
}
|
|
202
|
-
interface ExternalMatchSearchRequest {
|
|
203
|
-
duprId: string;
|
|
204
|
-
offset?: number;
|
|
205
|
-
limit?: number;
|
|
206
|
-
}
|
|
207
|
-
interface MatchResponse {
|
|
208
|
-
matchCode?: string;
|
|
209
|
-
hashedMatchCode?: string;
|
|
210
|
-
identifier?: string;
|
|
211
|
-
matchDate?: string;
|
|
212
|
-
matchFormat?: MatchFormat;
|
|
213
|
-
teams?: ExternalMatchTeam[];
|
|
214
|
-
}
|
|
215
|
-
interface SubscriptionItemRequest {
|
|
216
|
-
productId: string;
|
|
217
|
-
promotionId: string;
|
|
218
|
-
}
|
|
219
|
-
interface TargetUserRequest {
|
|
220
|
-
duprId?: string;
|
|
221
|
-
email?: string;
|
|
222
|
-
}
|
|
223
|
-
interface AttributionRequest {
|
|
224
|
-
clientKeyId: number;
|
|
225
|
-
}
|
|
226
|
-
interface GrantExternalSubscriptionRequest {
|
|
227
|
-
user: TargetUserRequest;
|
|
228
|
-
item: SubscriptionItemRequest;
|
|
229
|
-
attribution: AttributionRequest;
|
|
230
|
-
metadata?: Record<string, string>;
|
|
231
|
-
}
|
|
232
|
-
interface PlayerRatingSubscribeRequest {
|
|
233
|
-
duprIds: string[];
|
|
234
|
-
}
|
|
235
|
-
interface ExternalClubMemberRequest {
|
|
236
|
-
clubId: string;
|
|
237
|
-
}
|
|
238
|
-
interface ExternalClubMatchSearchRequest {
|
|
239
|
-
clubId: string;
|
|
240
|
-
offset?: number;
|
|
241
|
-
limit?: number;
|
|
242
|
-
}
|
|
243
|
-
interface CreateEventRequestV1 {
|
|
244
|
-
name: string;
|
|
245
|
-
description?: string;
|
|
246
|
-
startDate: string;
|
|
247
|
-
endDate: string;
|
|
248
|
-
location?: string;
|
|
249
|
-
clubId?: number;
|
|
250
|
-
}
|
|
251
|
-
interface UpdateEventRequestV1 {
|
|
252
|
-
eventId: string;
|
|
253
|
-
name?: string;
|
|
254
|
-
description?: string;
|
|
255
|
-
startDate?: string;
|
|
256
|
-
endDate?: string;
|
|
257
|
-
}
|
|
258
|
-
interface GetEventRequestV1 {
|
|
259
|
-
eventIds: string[];
|
|
260
|
-
}
|
|
261
|
-
interface DeleteEventRequestV1 {
|
|
262
|
-
eventIds: string[];
|
|
263
|
-
}
|
|
264
|
-
interface CreateEventResponseV1 {
|
|
265
|
-
eventId?: string;
|
|
266
|
-
name?: string;
|
|
267
|
-
}
|
|
268
|
-
interface UpdateEventResponseV1 {
|
|
269
|
-
eventId?: string;
|
|
270
|
-
}
|
|
271
|
-
interface GetEventResponseV1 {
|
|
272
|
-
events?: Array<{
|
|
273
|
-
eventId: string;
|
|
274
|
-
name: string;
|
|
275
|
-
description?: string;
|
|
276
|
-
startDate?: string;
|
|
277
|
-
endDate?: string;
|
|
278
|
-
location?: string;
|
|
279
|
-
}>;
|
|
280
|
-
}
|
|
281
|
-
interface DeleteEventResponseV1 {
|
|
282
|
-
deleted?: string[];
|
|
283
|
-
}
|
|
284
|
-
interface ClientHookRequest {
|
|
285
|
-
webhookUrl: string;
|
|
286
|
-
topics: WebhookTopic[];
|
|
287
|
-
}
|
|
288
|
-
interface UserWebhookRequest {
|
|
289
|
-
duprIds: string[];
|
|
290
|
-
topic: WebhookTopic;
|
|
291
|
-
}
|
|
292
|
-
interface WebhookSchema {
|
|
293
|
-
topic: string;
|
|
294
|
-
schema: Record<string, unknown>;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
interface AuthCodeTokenResponse extends TokenResponse {
|
|
298
|
-
refresh_token?: string;
|
|
299
|
-
token_type?: string;
|
|
300
|
-
scope?: string;
|
|
301
|
-
}
|
|
302
|
-
interface AuthorizationUrlParams {
|
|
303
|
-
/** Your OAuth redirect URI, must match what is registered with DUPR. */
|
|
304
|
-
redirectUri: string;
|
|
305
|
-
/** OAuth scopes to request (e.g. ["user.read"]). Defaults to empty. */
|
|
306
|
-
scopes?: string[];
|
|
307
|
-
/** Opaque value passed through the flow to prevent CSRF. Recommended. */
|
|
308
|
-
state?: string;
|
|
309
|
-
}
|
|
310
|
-
declare class AuthModule {
|
|
311
|
-
private readonly http;
|
|
312
|
-
private readonly config;
|
|
313
|
-
constructor(http: HttpClient, config: ResolvedConfig);
|
|
314
|
-
/**
|
|
315
|
-
* Explicitly request a new access token using client credentials.
|
|
316
|
-
* Normally you don't need to call this — the HTTP client handles token refresh automatically.
|
|
317
|
-
*/
|
|
318
|
-
getToken(): Promise<TokenResponse>;
|
|
319
|
-
/**
|
|
320
|
-
* Build the DUPR authorization URL to redirect the user to for login.
|
|
321
|
-
* The `authorizationUrl` config option must be set (see above note).
|
|
322
|
-
*/
|
|
323
|
-
getAuthorizationUrl(params: AuthorizationUrlParams): string;
|
|
324
|
-
/**
|
|
325
|
-
* Exchange an authorization code (from the OAuth callback) for access + refresh tokens.
|
|
326
|
-
* Uses `POST /auth/{version}/token` with `grant_type=authorization_code`.
|
|
327
|
-
*/
|
|
328
|
-
exchangeCode(params: {
|
|
329
|
-
code: string;
|
|
330
|
-
redirectUri: string;
|
|
331
|
-
}): Promise<AuthCodeTokenResponse>;
|
|
332
|
-
/**
|
|
333
|
-
* Obtain a new access token using a refresh token from a previous Authorization Code flow.
|
|
334
|
-
* Uses `POST /auth/{version}/token` with `grant_type=refresh_token`.
|
|
335
|
-
*/
|
|
336
|
-
refreshToken(refreshToken: string): Promise<AuthCodeTokenResponse>;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
declare class UsersModule {
|
|
340
|
-
private readonly http;
|
|
341
|
-
private readonly cfg;
|
|
342
|
-
constructor(http: HttpClient, cfg: ResolvedConfig);
|
|
343
|
-
/** GET /user/{version}/{id} — basic player profile */
|
|
344
|
-
getUser(duprId: string): Promise<ApiWrapper<UserInfo>>;
|
|
345
|
-
/** GET /user/{version}/{id}/details — extended profile (requires USER_EMAIL::VIEW permission) */
|
|
346
|
-
getExtendedUser(duprId: string): Promise<ApiWrapper<ExtendedUserInfo>>;
|
|
347
|
-
/** GET /user/{version}/{id}/clubs — club memberships for a player */
|
|
348
|
-
getClubMemberships(duprId: string): Promise<ClubMembershipResponse>;
|
|
349
|
-
/** POST /user/{version}/search — full-text player search with optional filters */
|
|
350
|
-
search(req: ExternalSearchRequest): Promise<ApiWrapper<UserInfo[]>>;
|
|
351
|
-
/** POST /user/{version}/batch — fetch multiple players by DUPR ID in one request */
|
|
352
|
-
getBatch(req: ExternalBatchUserDetailRequest): Promise<ApiWrapper<UserInfo[]>>;
|
|
353
|
-
/** POST /user/{version}/invite — pre-generate a DUPR ID and send an invite email */
|
|
354
|
-
invite(req: ExternalInviteRequest): Promise<ApiWrapper<{
|
|
355
|
-
duprId: string;
|
|
356
|
-
}>>;
|
|
357
|
-
/** POST /user/{version}/subscription/grants — grant a subscription to a user */
|
|
358
|
-
grantSubscription(req: GrantExternalSubscriptionRequest): Promise<ApiWrapper>;
|
|
359
|
-
/** POST /user/{version}/provisional_rating — get provisional ratings for a player */
|
|
360
|
-
getProvisionalRating(req: GetProvisionalRatingRequest): Promise<ApiWrapper>;
|
|
361
|
-
/** POST /user/{version}/provisional_rating/create */
|
|
362
|
-
createProvisionalRating(req: CreateProvisionalRatingRequest): Promise<ApiWrapper>;
|
|
363
|
-
/** POST /user/{version}/provisional_rating/update */
|
|
364
|
-
updateProvisionalRating(req: UpdateProvisionalRatingRequest): Promise<ApiWrapper>;
|
|
365
|
-
/** DELETE /user/{version}/provisional_rating/delete */
|
|
366
|
-
deleteProvisionalRating(req: DeleteProvisionalRatingRequest): Promise<ApiWrapper>;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
interface GetDuprIdByEmailRequest {
|
|
370
|
-
email: string;
|
|
371
|
-
}
|
|
372
|
-
interface DuprIdByEmailResponse {
|
|
373
|
-
duprId?: string;
|
|
374
|
-
}
|
|
375
|
-
declare class PlayersModule {
|
|
376
|
-
private readonly http;
|
|
377
|
-
private readonly cfg;
|
|
378
|
-
constructor(http: HttpClient, cfg: ResolvedConfig);
|
|
379
|
-
/** POST /{version}/player/duprid-by-email — resolve a DUPR ID from an email address */
|
|
380
|
-
getDuprIdByEmail(req: GetDuprIdByEmailRequest): Promise<ApiWrapper<DuprIdByEmailResponse>>;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
interface PlayerRatingHistoryRequest {
|
|
384
|
-
duprId: string;
|
|
385
|
-
offset?: number;
|
|
386
|
-
limit?: number;
|
|
387
|
-
}
|
|
388
|
-
interface PlayerRatingHistoryEntry {
|
|
389
|
-
date?: string;
|
|
390
|
-
singlesRating?: number;
|
|
391
|
-
doublesRating?: number;
|
|
392
|
-
}
|
|
393
|
-
declare class PlayerRatingModule {
|
|
394
|
-
private readonly http;
|
|
395
|
-
private readonly cfg;
|
|
396
|
-
constructor(http: HttpClient, cfg: ResolvedConfig);
|
|
397
|
-
/** POST /history — get rating history for a player */
|
|
398
|
-
getHistory(req: PlayerRatingHistoryRequest): Promise<ApiWrapper<PlayerRatingHistoryEntry[]>>;
|
|
399
|
-
/** GET /{version}/subscribe/rating-changes — list currently subscribed DUPR IDs */
|
|
400
|
-
getSubscriptions(): Promise<ApiWrapper<{
|
|
401
|
-
duprIds: string[];
|
|
402
|
-
}>>;
|
|
403
|
-
/** POST /{version}/subscribe/rating-changes — subscribe to rating-change events for a list of players */
|
|
404
|
-
subscribe(req: PlayerRatingSubscribeRequest): Promise<ApiWrapper>;
|
|
405
|
-
/** DELETE /{version}/subscribe/rating-changes — unsubscribe from rating-change events */
|
|
406
|
-
unsubscribe(req: PlayerRatingSubscribeRequest): Promise<ApiWrapper>;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
interface AnnotateMatchRequest {
|
|
410
|
-
matchId: string;
|
|
411
|
-
annotation: Record<string, unknown>;
|
|
412
|
-
}
|
|
413
|
-
declare class MatchesModule {
|
|
414
|
-
private readonly http;
|
|
415
|
-
private readonly cfg;
|
|
416
|
-
constructor(http: HttpClient, cfg: ResolvedConfig);
|
|
417
|
-
/** GET /match/{version}/{id} — view a single match */
|
|
418
|
-
get(matchId: string): Promise<ApiWrapper<MatchResponse>>;
|
|
419
|
-
/** POST /match/{version}/create — submit a new match result */
|
|
420
|
-
create(match: ExternalMatchRequest): Promise<ApiWrapper<MatchResponse>>;
|
|
421
|
-
/** POST /match/{version}/batch — submit multiple match results in one call */
|
|
422
|
-
createBulk(matches: ExternalMatchRequest[]): Promise<ApiWrapper<MatchResponse[]>>;
|
|
423
|
-
/** POST /match/{version}/update — update an existing match */
|
|
424
|
-
update(req: ExternalUpdateMatchRequest): Promise<ApiWrapper<MatchResponse>>;
|
|
425
|
-
/** DELETE /match/{version}/delete — delete a match */
|
|
426
|
-
delete(req: ExternalDeleteMatchRequest): Promise<ApiWrapper>;
|
|
427
|
-
/** POST /match/{version}/annotate — attach vendor-specific metadata to a match */
|
|
428
|
-
annotate(req: AnnotateMatchRequest): Promise<ApiWrapper>;
|
|
429
|
-
/** DELETE /match/{version}/annotate/{matchId} — remove a match annotation */
|
|
430
|
-
deleteAnnotation(matchId: string): Promise<ApiWrapper>;
|
|
431
|
-
/** POST /match/history/search — search a player's match history */
|
|
432
|
-
searchHistory(req: ExternalMatchSearchRequest): Promise<ApiWrapper<MatchResponse[]>>;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
declare class ClubsModule {
|
|
436
|
-
private readonly http;
|
|
437
|
-
private readonly cfg;
|
|
438
|
-
constructor(http: HttpClient, cfg: ResolvedConfig);
|
|
439
|
-
/** POST /club/{version}/members — get ratings for all members of a club */
|
|
440
|
-
membersRating(req: ExternalClubMemberRequest): Promise<ApiWrapper<UserInfo[]>>;
|
|
441
|
-
/** POST /club/{version}/match/search — search matches associated with a club */
|
|
442
|
-
searchMatches(req: ExternalClubMatchSearchRequest): Promise<ApiWrapper<MatchResponse[]>>;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
declare class EventsModule {
|
|
446
|
-
private readonly http;
|
|
447
|
-
private readonly cfg;
|
|
448
|
-
constructor(http: HttpClient, cfg: ResolvedConfig);
|
|
449
|
-
/** POST /events/{version}/create */
|
|
450
|
-
create(req: CreateEventRequestV1): Promise<ApiWrapper<CreateEventResponseV1>>;
|
|
451
|
-
/** GET /events/{version}/get */
|
|
452
|
-
get(req: GetEventRequestV1): Promise<ApiWrapper<GetEventResponseV1>>;
|
|
453
|
-
/** POST /events/{version}/update */
|
|
454
|
-
update(req: UpdateEventRequestV1): Promise<ApiWrapper<UpdateEventResponseV1>>;
|
|
455
|
-
/** POST /events/{version}/delete */
|
|
456
|
-
delete(req: DeleteEventRequestV1): Promise<ApiWrapper<DeleteEventResponseV1>>;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
declare class WebhooksModule {
|
|
460
|
-
private readonly http;
|
|
461
|
-
private readonly cfg;
|
|
462
|
-
constructor(http: HttpClient, cfg: ResolvedConfig);
|
|
463
|
-
/** POST /{version}/webhook — register a webhook endpoint */
|
|
464
|
-
register(req: ClientHookRequest): Promise<ApiWrapper>;
|
|
465
|
-
/** GET /{version}/topic — list all available webhook topics */
|
|
466
|
-
getTopics(): Promise<ApiWrapper<string[]>>;
|
|
467
|
-
/** GET /{version}/webhook/schema — list available webhook schemas */
|
|
468
|
-
listSchemas(): Promise<ApiWrapper<WebhookSchema[]>>;
|
|
469
|
-
/** GET /{version}/webhook/schema/{topic} — get the JSON schema for a specific topic */
|
|
470
|
-
getSchema(topic: string): Promise<ApiWrapper<WebhookSchema>>;
|
|
471
|
-
/** POST /user/{version}/subscribe/webhook-event — subscribe specific users to a webhook topic */
|
|
472
|
-
subscribeUsers(req: UserWebhookRequest): Promise<ApiWrapper>;
|
|
473
|
-
/** DELETE /user/{version}/subscribe/webhook-event — unsubscribe specific users from a webhook topic */
|
|
474
|
-
unsubscribeUsers(req: UserWebhookRequest): Promise<ApiWrapper>;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
declare class DuprClient {
|
|
478
|
-
readonly config: ResolvedConfig;
|
|
479
|
-
readonly auth: AuthModule;
|
|
480
|
-
readonly users: UsersModule;
|
|
481
|
-
readonly players: PlayersModule;
|
|
482
|
-
readonly playerRating: PlayerRatingModule;
|
|
483
|
-
readonly matches: MatchesModule;
|
|
484
|
-
readonly clubs: ClubsModule;
|
|
485
|
-
readonly events: EventsModule;
|
|
486
|
-
readonly webhooks: WebhooksModule;
|
|
487
|
-
constructor(opts?: DuprClientOptions);
|
|
488
|
-
/** Override the bearer token at runtime — useful when your backend handles auth separately. */
|
|
489
|
-
setBearerToken(token: string): void;
|
|
490
|
-
/** Clear the runtime bearer token override and fall back to configured auth. */
|
|
491
|
-
clearBearerToken(): void;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
declare class DuprApiError extends Error {
|
|
495
|
-
readonly statusCode: number;
|
|
496
|
-
readonly details?: unknown | undefined;
|
|
497
|
-
readonly duprRequestId?: string | undefined;
|
|
498
|
-
constructor(message: string, statusCode: number, details?: unknown | undefined, duprRequestId?: string | undefined);
|
|
499
|
-
}
|
|
500
|
-
declare class AuthenticationError extends DuprApiError {
|
|
501
|
-
constructor(message: string, statusCode: number, details?: unknown, duprRequestId?: string);
|
|
502
|
-
}
|
|
503
|
-
declare class ValidationError extends DuprApiError {
|
|
504
|
-
constructor(message: string, statusCode: number, details?: unknown, duprRequestId?: string);
|
|
505
|
-
}
|
|
506
|
-
declare class NotFoundError extends DuprApiError {
|
|
507
|
-
constructor(message: string, statusCode: number, details?: unknown, duprRequestId?: string);
|
|
508
|
-
}
|
|
509
|
-
declare class RateLimitError extends DuprApiError {
|
|
510
|
-
constructor(message: string, statusCode: number, details?: unknown, duprRequestId?: string);
|
|
511
|
-
}
|
|
512
|
-
declare class ServerError extends DuprApiError {
|
|
513
|
-
constructor(message: string, statusCode: number, details?: unknown, duprRequestId?: string);
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
export { type ApiStatus, type ApiWrapper, type AttributionRequest, type AuthCodeTokenResponse, type AuthMode, AuthModule, AuthenticationError, type AuthorizationUrlParams, type ClientHookRequest, type ClubMembership, type ClubMembershipResponse, ClubsModule, type CreateEventRequestV1, type CreateEventResponseV1, type CreateProvisionalRatingRequest, type DeleteEventRequestV1, type DeleteEventResponseV1, type DeleteProvisionalRatingRequest, DuprApiError, DuprClient, type DuprClientOptions, EventsModule, type ExtendedUserInfo, type ExternalAgeRangeFilter, type ExternalBatchUserDetailRequest, type ExternalClubMatchSearchRequest, type ExternalClubMemberRequest, type ExternalDeleteMatchRequest, type ExternalFilterLocation, type ExternalInviteRequest, type ExternalMatchPlayer, type ExternalMatchRequest, type ExternalMatchSearchRequest, type ExternalMatchTeam, type ExternalRatingFilter, type ExternalSearchFilter, type ExternalSearchRequest, type ExternalUpdateMatchRequest, type Gender, type GetEventRequestV1, type GetEventResponseV1, type GetProvisionalRatingRequest, type GrantExternalSubscriptionRequest, type MatchFormat, type MatchResponse, type MatchSource, MatchesModule, NotFoundError, PlayerRatingModule, type PlayerRatingSubscribeRequest, PlayersModule, RateLimitError, type RatingCoach, type RatingType, type RequestInfo, type ResolvedConfig, type ResolvedRetryOptions, type ResponseInfo, type RetryOptions, ServerError, type SubscriptionItemRequest, type TargetUserRequest, type TokenResponse, type UpdateEventRequestV1, type UpdateEventResponseV1, type UpdateProvisionalRatingRequest, type UserInfo, type UserWebhookRequest, UsersModule, ValidationError, type WebhookSchema, type WebhookTopic, WebhooksModule };
|