@predictorsdk/client 0.3.1 → 0.3.2
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/dist/BaseClient.d.ts +3 -0
- package/dist/BaseClient.js +15 -0
- package/dist/Client.js +15 -3
- package/dist/core/auth/AuthProvider.d.ts +1 -0
- package/dist/core/auth/AuthProvider.js +6 -1
- package/dist/core/auth/index.d.ts +1 -1
- package/dist/core/auth/index.js +1 -0
- package/dist/core/fetcher/Fetcher.d.ts +6 -0
- package/dist/core/fetcher/Fetcher.js +9 -8
- package/dist/core/fetcher/requestWithRetries.js +4 -1
- package/dist/core/schemas/builders/enum/enum.d.ts +1 -0
- package/dist/core/schemas/builders/enum/enum.js +6 -0
- package/dist/core/schemas/builders/enum/index.d.ts +1 -1
- package/dist/core/schemas/builders/enum/index.js +1 -1
- package/dist/core/schemas/builders/schema-utils/JsonError.js +2 -1
- package/dist/core/schemas/builders/schema-utils/ParseError.js +2 -1
- package/dist/core/url/QueryStringBuilder.d.ts +47 -0
- package/dist/core/url/QueryStringBuilder.js +78 -0
- package/dist/core/url/index.d.ts +1 -0
- package/dist/core/url/index.js +1 -0
- package/dist/core/url/qs.d.ts +2 -1
- package/dist/core/url/qs.js +24 -12
- package/package.json +1 -1
package/dist/BaseClient.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BearerAuthProvider } from "./auth/BearerAuthProvider.js";
|
|
2
2
|
import * as core from "./core/index.js";
|
|
3
3
|
import type * as environments from "./environments.js";
|
|
4
|
+
export type AuthOption = false | core.AuthProvider["getAuthRequest"] | core.AuthProvider | BearerAuthProvider.AuthOptions;
|
|
4
5
|
export type BaseClientOptions = {
|
|
5
6
|
environment?: core.Supplier<environments.PredictorSDKEnvironment | string>;
|
|
6
7
|
/** Specify a custom URL to connect the client to. */
|
|
@@ -15,6 +16,8 @@ export type BaseClientOptions = {
|
|
|
15
16
|
fetch?: typeof fetch;
|
|
16
17
|
/** Configure logging for the client. */
|
|
17
18
|
logging?: core.logging.LogConfig | core.logging.Logger;
|
|
19
|
+
/** Override auth. Pass false to disable, a function returning auth headers, an AuthProvider, or auth options. */
|
|
20
|
+
auth?: AuthOption;
|
|
18
21
|
} & BearerAuthProvider.AuthOptions;
|
|
19
22
|
export interface BaseRequestOptions {
|
|
20
23
|
/** The maximum time to wait for a response in seconds. */
|
package/dist/BaseClient.js
CHANGED
|
@@ -16,6 +16,21 @@ export function normalizeClientOptions(options) {
|
|
|
16
16
|
}
|
|
17
17
|
export function normalizeClientOptionsWithAuth(options) {
|
|
18
18
|
const normalized = normalizeClientOptions(options);
|
|
19
|
+
if (options.auth === false) {
|
|
20
|
+
normalized.authProvider = new core.NoOpAuthProvider();
|
|
21
|
+
return normalized;
|
|
22
|
+
}
|
|
23
|
+
if (options.auth != null) {
|
|
24
|
+
if (typeof options.auth === "function") {
|
|
25
|
+
normalized.authProvider = { getAuthRequest: options.auth };
|
|
26
|
+
return normalized;
|
|
27
|
+
}
|
|
28
|
+
if (core.isAuthProvider(options.auth)) {
|
|
29
|
+
normalized.authProvider = options.auth;
|
|
30
|
+
return normalized;
|
|
31
|
+
}
|
|
32
|
+
Object.assign(normalized, options.auth);
|
|
33
|
+
}
|
|
19
34
|
const normalizedWithNoOpAuthProvider = withNoOpAuthProvider(normalized);
|
|
20
35
|
normalized.authProvider ??= new BearerAuthProvider(normalizedWithNoOpAuthProvider);
|
|
21
36
|
return normalized;
|
package/dist/Client.js
CHANGED
|
@@ -50,7 +50,11 @@ export class PredictorSDKClient {
|
|
|
50
50
|
environments.PredictorSDKEnvironment.Production, "v1/matching-markets/sports"),
|
|
51
51
|
method: "GET",
|
|
52
52
|
headers: _headers,
|
|
53
|
-
|
|
53
|
+
queryString: core.url
|
|
54
|
+
.queryBuilder()
|
|
55
|
+
.addMany(_queryParams)
|
|
56
|
+
.mergeAdditional(requestOptions?.queryParams)
|
|
57
|
+
.build(),
|
|
54
58
|
timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
|
|
55
59
|
maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
|
|
56
60
|
abortSignal: requestOptions?.abortSignal,
|
|
@@ -162,7 +166,11 @@ export class PredictorSDKClient {
|
|
|
162
166
|
environments.PredictorSDKEnvironment.Production, "v1/markets"),
|
|
163
167
|
method: "GET",
|
|
164
168
|
headers: _headers,
|
|
165
|
-
|
|
169
|
+
queryString: core.url
|
|
170
|
+
.queryBuilder()
|
|
171
|
+
.addMany(_queryParams)
|
|
172
|
+
.mergeAdditional(requestOptions?.queryParams)
|
|
173
|
+
.build(),
|
|
166
174
|
timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
|
|
167
175
|
maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
|
|
168
176
|
abortSignal: requestOptions?.abortSignal,
|
|
@@ -280,7 +288,11 @@ export class PredictorSDKClient {
|
|
|
280
288
|
environments.PredictorSDKEnvironment.Production, "v1/crypto-prices/binance"),
|
|
281
289
|
method: "GET",
|
|
282
290
|
headers: _headers,
|
|
283
|
-
|
|
291
|
+
queryString: core.url
|
|
292
|
+
.queryBuilder()
|
|
293
|
+
.addMany(_queryParams)
|
|
294
|
+
.mergeAdditional(requestOptions?.queryParams)
|
|
295
|
+
.build(),
|
|
284
296
|
timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
|
|
285
297
|
maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
|
|
286
298
|
abortSignal: requestOptions?.abortSignal,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export { type AuthProvider, isAuthProvider } from "./AuthProvider.js";
|
|
2
2
|
export type { AuthRequest } from "./AuthRequest.js";
|
|
3
3
|
export { BasicAuth } from "./BasicAuth.js";
|
|
4
4
|
export { BearerToken } from "./BearerToken.js";
|
package/dist/core/auth/index.js
CHANGED
|
@@ -8,7 +8,13 @@ export declare namespace Fetcher {
|
|
|
8
8
|
method: string;
|
|
9
9
|
contentType?: string;
|
|
10
10
|
headers?: Record<string, unknown>;
|
|
11
|
+
/**
|
|
12
|
+
* @deprecated Prefer `queryString` (produced by `core.url.queryBuilder()`).
|
|
13
|
+
* Retained for backwards compatibility with custom fetchers and callers that
|
|
14
|
+
* still construct request args with a query-parameter object.
|
|
15
|
+
*/
|
|
11
16
|
queryParameters?: Record<string, unknown>;
|
|
17
|
+
queryString?: string;
|
|
12
18
|
body?: unknown;
|
|
13
19
|
timeoutMs?: number;
|
|
14
20
|
maxRetries?: number;
|
|
@@ -62,16 +62,11 @@ const SENSITIVE_QUERY_PARAMS = new Set([
|
|
|
62
62
|
]);
|
|
63
63
|
function redactQueryParameters(queryParameters) {
|
|
64
64
|
if (queryParameters == null) {
|
|
65
|
-
return
|
|
65
|
+
return undefined;
|
|
66
66
|
}
|
|
67
67
|
const redacted = {};
|
|
68
68
|
for (const [key, value] of Object.entries(queryParameters)) {
|
|
69
|
-
|
|
70
|
-
redacted[key] = "[REDACTED]";
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
redacted[key] = value;
|
|
74
|
-
}
|
|
69
|
+
redacted[key] = SENSITIVE_QUERY_PARAMS.has(key.toLowerCase()) ? "[REDACTED]" : value;
|
|
75
70
|
}
|
|
76
71
|
return redacted;
|
|
77
72
|
}
|
|
@@ -168,7 +163,13 @@ async function getHeaders(args) {
|
|
|
168
163
|
return newHeaders;
|
|
169
164
|
}
|
|
170
165
|
export async function fetcherImpl(args) {
|
|
171
|
-
|
|
166
|
+
let url = args.url;
|
|
167
|
+
if (args.queryString != null && args.queryString.length > 0) {
|
|
168
|
+
url = `${url}?${args.queryString}`;
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
url = createRequestUrl(args.url, args.queryParameters);
|
|
172
|
+
}
|
|
172
173
|
const requestBody = await getRequestBody({
|
|
173
174
|
body: args.body,
|
|
174
175
|
type: args.requestType ?? "other",
|
|
@@ -2,6 +2,9 @@ const INITIAL_RETRY_DELAY = 1000; // in milliseconds
|
|
|
2
2
|
const MAX_RETRY_DELAY = 60000; // in milliseconds
|
|
3
3
|
const DEFAULT_MAX_RETRIES = 2;
|
|
4
4
|
const JITTER_FACTOR = 0.2; // 20% random jitter
|
|
5
|
+
function isRetryableStatusCode(statusCode) {
|
|
6
|
+
return [408, 429].includes(statusCode) || statusCode >= 500;
|
|
7
|
+
}
|
|
5
8
|
function addPositiveJitter(delay) {
|
|
6
9
|
const jitterMultiplier = 1 + Math.random() * JITTER_FACTOR;
|
|
7
10
|
return delay * jitterMultiplier;
|
|
@@ -40,7 +43,7 @@ function getRetryDelayFromHeaders(response, retryAttempt) {
|
|
|
40
43
|
export async function requestWithRetries(requestFn, maxRetries = DEFAULT_MAX_RETRIES) {
|
|
41
44
|
let response = await requestFn();
|
|
42
45
|
for (let i = 0; i < maxRetries; ++i) {
|
|
43
|
-
if (
|
|
46
|
+
if (isRetryableStatusCode(response.status)) {
|
|
44
47
|
const delay = getRetryDelayFromHeaders(response, i);
|
|
45
48
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
46
49
|
response = await requestFn();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { enum_ } from "./enum.js";
|
|
1
|
+
export { enum_, forwardCompatibleEnum_ } from "./enum.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { enum_ } from "./enum.js";
|
|
1
|
+
export { enum_, forwardCompatibleEnum_ } from "./enum.js";
|
|
@@ -4,6 +4,7 @@ export class JsonError extends Error {
|
|
|
4
4
|
constructor(errors) {
|
|
5
5
|
super(errors.map(stringifyValidationError).join("; "));
|
|
6
6
|
this.errors = errors;
|
|
7
|
-
Object.setPrototypeOf(this,
|
|
7
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
8
|
+
this.name = this.constructor.name;
|
|
8
9
|
}
|
|
9
10
|
}
|
|
@@ -4,6 +4,7 @@ export class ParseError extends Error {
|
|
|
4
4
|
constructor(errors) {
|
|
5
5
|
super(errors.map(stringifyValidationError).join("; "));
|
|
6
6
|
this.errors = errors;
|
|
7
|
-
Object.setPrototypeOf(this,
|
|
7
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
8
|
+
this.name = this.constructor.name;
|
|
8
9
|
}
|
|
9
10
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a fluent builder for constructing URL query strings.
|
|
3
|
+
*
|
|
4
|
+
* Each `.add()` call serializes its value immediately (like C#'s builder),
|
|
5
|
+
* so no format tracking is needed — the style is applied at add-time.
|
|
6
|
+
*
|
|
7
|
+
* Usage (generated code):
|
|
8
|
+
*
|
|
9
|
+
* const qs = core.url.queryBuilder()
|
|
10
|
+
* .add("limit", limit)
|
|
11
|
+
* .add("tags", tags, { style: "comma" }) // explode: false
|
|
12
|
+
* .mergeAdditional(requestOptions?.queryParams)
|
|
13
|
+
* .build();
|
|
14
|
+
*/
|
|
15
|
+
export declare function queryBuilder(): QueryStringBuilder;
|
|
16
|
+
declare class QueryStringBuilder {
|
|
17
|
+
private parts;
|
|
18
|
+
/**
|
|
19
|
+
* Adds a query parameter, serializing it immediately.
|
|
20
|
+
*
|
|
21
|
+
* By default arrays use "repeat" format (`key=a&key=b`).
|
|
22
|
+
* Pass `{ style: "comma" }` for OpenAPI `explode: false` parameters
|
|
23
|
+
* to get comma-separated values (`key=a,b,c`).
|
|
24
|
+
*
|
|
25
|
+
* Null / undefined values are silently skipped.
|
|
26
|
+
*/
|
|
27
|
+
add(key: string, value: unknown, options?: {
|
|
28
|
+
style?: "comma";
|
|
29
|
+
}): this;
|
|
30
|
+
/**
|
|
31
|
+
* Adds multiple query parameters at once from a record.
|
|
32
|
+
* All parameters use the default "repeat" array format.
|
|
33
|
+
* Null / undefined values are silently skipped.
|
|
34
|
+
*/
|
|
35
|
+
addMany(params: Record<string, unknown>): this;
|
|
36
|
+
/**
|
|
37
|
+
* Merges additional query parameters supplied at call-time via
|
|
38
|
+
* `requestOptions.queryParams`. Overrides existing keys (last-write-wins).
|
|
39
|
+
*/
|
|
40
|
+
mergeAdditional(additionalParams?: Record<string, unknown>): this;
|
|
41
|
+
/**
|
|
42
|
+
* Returns the assembled query string (without the leading `?`).
|
|
43
|
+
* Returns an empty string when no parameters were added.
|
|
44
|
+
*/
|
|
45
|
+
build(): string;
|
|
46
|
+
}
|
|
47
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { toQueryString } from "./qs.js";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a fluent builder for constructing URL query strings.
|
|
4
|
+
*
|
|
5
|
+
* Each `.add()` call serializes its value immediately (like C#'s builder),
|
|
6
|
+
* so no format tracking is needed — the style is applied at add-time.
|
|
7
|
+
*
|
|
8
|
+
* Usage (generated code):
|
|
9
|
+
*
|
|
10
|
+
* const qs = core.url.queryBuilder()
|
|
11
|
+
* .add("limit", limit)
|
|
12
|
+
* .add("tags", tags, { style: "comma" }) // explode: false
|
|
13
|
+
* .mergeAdditional(requestOptions?.queryParams)
|
|
14
|
+
* .build();
|
|
15
|
+
*/
|
|
16
|
+
export function queryBuilder() {
|
|
17
|
+
return new QueryStringBuilder();
|
|
18
|
+
}
|
|
19
|
+
class QueryStringBuilder {
|
|
20
|
+
parts = new Map();
|
|
21
|
+
/**
|
|
22
|
+
* Adds a query parameter, serializing it immediately.
|
|
23
|
+
*
|
|
24
|
+
* By default arrays use "repeat" format (`key=a&key=b`).
|
|
25
|
+
* Pass `{ style: "comma" }` for OpenAPI `explode: false` parameters
|
|
26
|
+
* to get comma-separated values (`key=a,b,c`).
|
|
27
|
+
*
|
|
28
|
+
* Null / undefined values are silently skipped.
|
|
29
|
+
*/
|
|
30
|
+
add(key, value, options) {
|
|
31
|
+
if (value === undefined || value === null) {
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
const serialized = toQueryString({ [key]: value }, { arrayFormat: options?.style === "comma" ? "comma" : "repeat" });
|
|
35
|
+
if (serialized.length > 0) {
|
|
36
|
+
this.parts.set(key, serialized);
|
|
37
|
+
}
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Adds multiple query parameters at once from a record.
|
|
42
|
+
* All parameters use the default "repeat" array format.
|
|
43
|
+
* Null / undefined values are silently skipped.
|
|
44
|
+
*/
|
|
45
|
+
addMany(params) {
|
|
46
|
+
if (params != null) {
|
|
47
|
+
for (const [key, value] of Object.entries(params)) {
|
|
48
|
+
this.add(key, value);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Merges additional query parameters supplied at call-time via
|
|
55
|
+
* `requestOptions.queryParams`. Overrides existing keys (last-write-wins).
|
|
56
|
+
*/
|
|
57
|
+
mergeAdditional(additionalParams) {
|
|
58
|
+
if (additionalParams != null) {
|
|
59
|
+
for (const [key, value] of Object.entries(additionalParams)) {
|
|
60
|
+
if (value === undefined || value === null) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const serialized = toQueryString({ [key]: value }, { arrayFormat: "repeat" });
|
|
64
|
+
if (serialized.length > 0) {
|
|
65
|
+
this.parts.set(key, serialized);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return this;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Returns the assembled query string (without the leading `?`).
|
|
73
|
+
* Returns an empty string when no parameters were added.
|
|
74
|
+
*/
|
|
75
|
+
build() {
|
|
76
|
+
return [...this.parts.values()].join("&");
|
|
77
|
+
}
|
|
78
|
+
}
|
package/dist/core/url/index.d.ts
CHANGED
package/dist/core/url/index.js
CHANGED
package/dist/core/url/qs.d.ts
CHANGED
package/dist/core/url/qs.js
CHANGED
|
@@ -23,19 +23,31 @@ function stringifyObject(obj, prefix = "", options) {
|
|
|
23
23
|
if (value.length === 0) {
|
|
24
24
|
continue;
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
const effectiveFormat = options.arrayFormat;
|
|
27
|
+
if (effectiveFormat === "comma") {
|
|
28
|
+
const encodedKey = options.encode ? encodeURIComponent(fullKey) : fullKey;
|
|
29
|
+
const encodedValues = value
|
|
30
|
+
.filter((item) => item !== undefined && item !== null)
|
|
31
|
+
.map((item) => encodeValue(item, options.encode));
|
|
32
|
+
if (encodedValues.length > 0) {
|
|
33
|
+
parts.push(`${encodedKey}=${encodedValues.join(",")}`);
|
|
30
34
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
for (let i = 0; i < value.length; i++) {
|
|
38
|
+
const item = value[i];
|
|
39
|
+
if (item === undefined) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (typeof item === "object" && !Array.isArray(item) && item !== null) {
|
|
43
|
+
const arrayKey = effectiveFormat === "indices" ? `${fullKey}[${i}]` : fullKey;
|
|
44
|
+
parts.push(...stringifyObject(item, arrayKey, options));
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const arrayKey = effectiveFormat === "indices" ? `${fullKey}[${i}]` : fullKey;
|
|
48
|
+
const encodedKey = options.encode ? encodeURIComponent(arrayKey) : arrayKey;
|
|
49
|
+
parts.push(`${encodedKey}=${encodeValue(item, options.encode)}`);
|
|
50
|
+
}
|
|
39
51
|
}
|
|
40
52
|
}
|
|
41
53
|
}
|