@predictorsdk/client 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/dist/BaseClient.d.ts +12 -0
- package/dist/Client.d.ts +22 -0
- package/dist/Client.js +54 -0
- package/dist/api/client/requests/GetMarketsRequest.d.ts +1 -1
- package/dist/api/errors/BadGatewayError.js +1 -1
- package/dist/api/errors/BadRequestError.js +1 -1
- package/dist/api/errors/ForbiddenError.js +1 -1
- package/dist/api/errors/NotFoundError.js +1 -1
- package/dist/api/errors/PaymentRequiredError.js +1 -1
- package/dist/api/errors/ServiceUnavailableError.js +1 -1
- package/dist/api/errors/TooManyRequestsError.js +1 -1
- package/dist/api/errors/UnauthorizedError.js +1 -1
- package/dist/api/types/PaymentRequiredErrorAction.d.ts +1 -1
- package/dist/api/types/PaymentRequiredErrorAction.js +1 -1
- package/dist/api/types/PaymentRequiredErrorBody.d.ts +0 -1
- package/dist/core/fetcher/Fetcher.js +1 -84
- package/dist/core/fetcher/getResponseBody.js +11 -0
- package/dist/core/fetcher/makePassthroughRequest.js +26 -4
- package/dist/core/fetcher/redactUrl.d.ts +2 -0
- package/dist/core/fetcher/redactUrl.js +84 -0
- package/dist/core/fetcher/requestWithRetries.js +2 -2
- package/dist/core/fetcher/signals.js +9 -1
- package/dist/core/requestBody.d.ts +12 -0
- package/dist/core/requestBody.js +23 -0
- package/dist/core/runtime/index.d.ts +1 -1
- package/dist/core/runtime/index.js +1 -1
- package/dist/core/runtime/runtime.d.ts +19 -0
- package/dist/core/runtime/runtime.js +71 -0
- package/dist/core/schemas/builders/schema-utils/JsonError.js +2 -2
- package/dist/core/schemas/builders/schema-utils/ParseError.js +2 -2
- package/dist/core/url/qs.js +2 -2
- package/dist/errors/PredictorSDKError.d.ts +1 -0
- package/dist/errors/PredictorSDKError.js +4 -1
- package/dist/errors/PredictorSDKTimeoutError.d.ts +2 -2
- package/dist/errors/PredictorSDKTimeoutError.js +7 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @predictorsdk/client
|
|
2
2
|
|
|
3
|
-
The official TypeScript/JavaScript client for the [PredictorSDK](https://predictorsdk.com)
|
|
3
|
+
The official TypeScript/JavaScript client for the [PredictorSDK](https://predictorsdk.com) prediction-market data API.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -15,9 +15,11 @@ import { PredictorSDKClient } from "@predictorsdk/client";
|
|
|
15
15
|
|
|
16
16
|
const client = new PredictorSDKClient({ token: "your-api-key" });
|
|
17
17
|
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
});
|
|
18
|
+
const plans = await client.getPlans();
|
|
19
|
+
const categories = await client.getCategories();
|
|
20
|
+
const markets = await client.getMarkets({ limit: 10, category: "sports" });
|
|
21
|
+
|
|
22
|
+
console.log(plans.data, categories.data, markets.data);
|
|
21
23
|
```
|
|
22
24
|
|
|
23
25
|
## Documentation
|
package/dist/BaseClient.d.ts
CHANGED
|
@@ -16,6 +16,11 @@ export type BaseClientOptions = {
|
|
|
16
16
|
fetch?: typeof fetch;
|
|
17
17
|
/** Configure logging for the client. */
|
|
18
18
|
logging?: core.logging.LogConfig | core.logging.Logger;
|
|
19
|
+
/** Default options for SSE stream reconnection behavior. Has no effect on non-resumable endpoints. */
|
|
20
|
+
stream?: {
|
|
21
|
+
reconnectionEnabled?: boolean;
|
|
22
|
+
maxReconnectionAttempts?: number;
|
|
23
|
+
};
|
|
19
24
|
/** Override auth. Pass false to disable, a function returning auth headers, an AuthProvider, or auth options. */
|
|
20
25
|
auth?: AuthOption;
|
|
21
26
|
} & BearerAuthProvider.AuthOptions;
|
|
@@ -28,8 +33,15 @@ export interface BaseRequestOptions {
|
|
|
28
33
|
abortSignal?: AbortSignal;
|
|
29
34
|
/** Additional query string parameters to include in the request. */
|
|
30
35
|
queryParams?: Record<string, unknown>;
|
|
36
|
+
/** A dictionary containing additional parameters to spread into the request's body. */
|
|
37
|
+
additionalBodyParameters?: Record<string, unknown>;
|
|
31
38
|
/** Additional headers to include in the request. */
|
|
32
39
|
headers?: Record<string, string | core.Supplier<string | null | undefined> | null | undefined>;
|
|
40
|
+
/** Options for SSE stream reconnection behavior. Has no effect on non-resumable endpoints. */
|
|
41
|
+
stream?: {
|
|
42
|
+
reconnectionEnabled?: boolean;
|
|
43
|
+
maxReconnectionAttempts?: number;
|
|
44
|
+
};
|
|
33
45
|
}
|
|
34
46
|
export type NormalizedClientOptions<T extends BaseClientOptions = BaseClientOptions> = T & {
|
|
35
47
|
logging: core.logging.Logger;
|
package/dist/Client.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export declare class PredictorSDKClient {
|
|
|
16
16
|
* @param {PredictorSDKClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
17
17
|
*
|
|
18
18
|
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
19
|
+
* @throws {@link errors.PredictorSDKError}
|
|
20
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
19
21
|
*
|
|
20
22
|
* @example
|
|
21
23
|
* await client.getPlans()
|
|
@@ -33,7 +35,10 @@ export declare class PredictorSDKClient {
|
|
|
33
35
|
* @throws {@link PredictorSDK.PaymentRequiredError}
|
|
34
36
|
* @throws {@link PredictorSDK.ForbiddenError}
|
|
35
37
|
* @throws {@link PredictorSDK.TooManyRequestsError}
|
|
38
|
+
* @throws {@link PredictorSDK.BadGatewayError}
|
|
36
39
|
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
40
|
+
* @throws {@link errors.PredictorSDKError}
|
|
41
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
37
42
|
*
|
|
38
43
|
* @example
|
|
39
44
|
* await client.getSportsMatchingMarkets()
|
|
@@ -51,7 +56,10 @@ export declare class PredictorSDKClient {
|
|
|
51
56
|
* @throws {@link PredictorSDK.PaymentRequiredError}
|
|
52
57
|
* @throws {@link PredictorSDK.ForbiddenError}
|
|
53
58
|
* @throws {@link PredictorSDK.TooManyRequestsError}
|
|
59
|
+
* @throws {@link PredictorSDK.BadGatewayError}
|
|
54
60
|
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
61
|
+
* @throws {@link errors.PredictorSDKError}
|
|
62
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
55
63
|
*
|
|
56
64
|
* @example
|
|
57
65
|
* await client.getMarkets()
|
|
@@ -67,6 +75,10 @@ export declare class PredictorSDKClient {
|
|
|
67
75
|
* @throws {@link PredictorSDK.PaymentRequiredError}
|
|
68
76
|
* @throws {@link PredictorSDK.ForbiddenError}
|
|
69
77
|
* @throws {@link PredictorSDK.TooManyRequestsError}
|
|
78
|
+
* @throws {@link PredictorSDK.BadGatewayError}
|
|
79
|
+
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
80
|
+
* @throws {@link errors.PredictorSDKError}
|
|
81
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
70
82
|
*
|
|
71
83
|
* @example
|
|
72
84
|
* await client.getCategories()
|
|
@@ -91,6 +103,8 @@ export declare class PredictorSDKClient {
|
|
|
91
103
|
* @throws {@link PredictorSDK.TooManyRequestsError}
|
|
92
104
|
* @throws {@link PredictorSDK.BadGatewayError}
|
|
93
105
|
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
106
|
+
* @throws {@link errors.PredictorSDKError}
|
|
107
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
94
108
|
*
|
|
95
109
|
* @example
|
|
96
110
|
* await client.getMarket({
|
|
@@ -112,6 +126,8 @@ export declare class PredictorSDKClient {
|
|
|
112
126
|
* @throws {@link PredictorSDK.TooManyRequestsError}
|
|
113
127
|
* @throws {@link PredictorSDK.BadGatewayError}
|
|
114
128
|
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
129
|
+
* @throws {@link errors.PredictorSDKError}
|
|
130
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
115
131
|
*
|
|
116
132
|
* @example
|
|
117
133
|
* await client.getBinanceCryptoPrices({
|
|
@@ -138,6 +154,8 @@ export declare class PredictorSDKClient {
|
|
|
138
154
|
* @throws {@link PredictorSDK.TooManyRequestsError}
|
|
139
155
|
* @throws {@link PredictorSDK.BadGatewayError}
|
|
140
156
|
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
157
|
+
* @throws {@link errors.PredictorSDKError}
|
|
158
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
141
159
|
*
|
|
142
160
|
* @example
|
|
143
161
|
* await client.getPolymarketWallet({
|
|
@@ -166,6 +184,8 @@ export declare class PredictorSDKClient {
|
|
|
166
184
|
* @throws {@link PredictorSDK.TooManyRequestsError}
|
|
167
185
|
* @throws {@link PredictorSDK.BadGatewayError}
|
|
168
186
|
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
187
|
+
* @throws {@link errors.PredictorSDKError}
|
|
188
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
169
189
|
*
|
|
170
190
|
* @example
|
|
171
191
|
* await client.listPolymarketWalletPositions({
|
|
@@ -194,6 +214,8 @@ export declare class PredictorSDKClient {
|
|
|
194
214
|
* @throws {@link PredictorSDK.TooManyRequestsError}
|
|
195
215
|
* @throws {@link PredictorSDK.BadGatewayError}
|
|
196
216
|
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
217
|
+
* @throws {@link errors.PredictorSDKError}
|
|
218
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
197
219
|
*
|
|
198
220
|
* @example
|
|
199
221
|
* await client.getEvent({
|
package/dist/Client.js
CHANGED
|
@@ -18,6 +18,8 @@ export class PredictorSDKClient {
|
|
|
18
18
|
* @param {PredictorSDKClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
19
19
|
*
|
|
20
20
|
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
21
|
+
* @throws {@link errors.PredictorSDKError}
|
|
22
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
21
23
|
*
|
|
22
24
|
* @example
|
|
23
25
|
* await client.getPlans()
|
|
@@ -83,7 +85,10 @@ export class PredictorSDKClient {
|
|
|
83
85
|
* @throws {@link PredictorSDK.PaymentRequiredError}
|
|
84
86
|
* @throws {@link PredictorSDK.ForbiddenError}
|
|
85
87
|
* @throws {@link PredictorSDK.TooManyRequestsError}
|
|
88
|
+
* @throws {@link PredictorSDK.BadGatewayError}
|
|
86
89
|
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
90
|
+
* @throws {@link errors.PredictorSDKError}
|
|
91
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
87
92
|
*
|
|
88
93
|
* @example
|
|
89
94
|
* await client.getSportsMatchingMarkets()
|
|
@@ -177,6 +182,14 @@ export class PredictorSDKClient {
|
|
|
177
182
|
skipValidation: true,
|
|
178
183
|
breadcrumbsPrefix: ["response"],
|
|
179
184
|
}), _response.rawResponse);
|
|
185
|
+
case 502:
|
|
186
|
+
throw new PredictorSDK.BadGatewayError(serializers.ErrorResponse.parseOrThrow(_response.error.body, {
|
|
187
|
+
unrecognizedObjectKeys: "passthrough",
|
|
188
|
+
allowUnrecognizedUnionMembers: true,
|
|
189
|
+
allowUnrecognizedEnumValues: true,
|
|
190
|
+
skipValidation: true,
|
|
191
|
+
breadcrumbsPrefix: ["response"],
|
|
192
|
+
}), _response.rawResponse);
|
|
180
193
|
case 503:
|
|
181
194
|
throw new PredictorSDK.ServiceUnavailableError(serializers.ErrorResponse.parseOrThrow(_response.error.body, {
|
|
182
195
|
unrecognizedObjectKeys: "passthrough",
|
|
@@ -206,7 +219,10 @@ export class PredictorSDKClient {
|
|
|
206
219
|
* @throws {@link PredictorSDK.PaymentRequiredError}
|
|
207
220
|
* @throws {@link PredictorSDK.ForbiddenError}
|
|
208
221
|
* @throws {@link PredictorSDK.TooManyRequestsError}
|
|
222
|
+
* @throws {@link PredictorSDK.BadGatewayError}
|
|
209
223
|
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
224
|
+
* @throws {@link errors.PredictorSDKError}
|
|
225
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
210
226
|
*
|
|
211
227
|
* @example
|
|
212
228
|
* await client.getMarkets()
|
|
@@ -299,6 +315,14 @@ export class PredictorSDKClient {
|
|
|
299
315
|
skipValidation: true,
|
|
300
316
|
breadcrumbsPrefix: ["response"],
|
|
301
317
|
}), _response.rawResponse);
|
|
318
|
+
case 502:
|
|
319
|
+
throw new PredictorSDK.BadGatewayError(serializers.ErrorResponse.parseOrThrow(_response.error.body, {
|
|
320
|
+
unrecognizedObjectKeys: "passthrough",
|
|
321
|
+
allowUnrecognizedUnionMembers: true,
|
|
322
|
+
allowUnrecognizedEnumValues: true,
|
|
323
|
+
skipValidation: true,
|
|
324
|
+
breadcrumbsPrefix: ["response"],
|
|
325
|
+
}), _response.rawResponse);
|
|
302
326
|
case 503:
|
|
303
327
|
throw new PredictorSDK.ServiceUnavailableError(serializers.ErrorResponse.parseOrThrow(_response.error.body, {
|
|
304
328
|
unrecognizedObjectKeys: "passthrough",
|
|
@@ -326,6 +350,10 @@ export class PredictorSDKClient {
|
|
|
326
350
|
* @throws {@link PredictorSDK.PaymentRequiredError}
|
|
327
351
|
* @throws {@link PredictorSDK.ForbiddenError}
|
|
328
352
|
* @throws {@link PredictorSDK.TooManyRequestsError}
|
|
353
|
+
* @throws {@link PredictorSDK.BadGatewayError}
|
|
354
|
+
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
355
|
+
* @throws {@link errors.PredictorSDKError}
|
|
356
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
329
357
|
*
|
|
330
358
|
* @example
|
|
331
359
|
* await client.getCategories()
|
|
@@ -395,6 +423,22 @@ export class PredictorSDKClient {
|
|
|
395
423
|
skipValidation: true,
|
|
396
424
|
breadcrumbsPrefix: ["response"],
|
|
397
425
|
}), _response.rawResponse);
|
|
426
|
+
case 502:
|
|
427
|
+
throw new PredictorSDK.BadGatewayError(serializers.ErrorResponse.parseOrThrow(_response.error.body, {
|
|
428
|
+
unrecognizedObjectKeys: "passthrough",
|
|
429
|
+
allowUnrecognizedUnionMembers: true,
|
|
430
|
+
allowUnrecognizedEnumValues: true,
|
|
431
|
+
skipValidation: true,
|
|
432
|
+
breadcrumbsPrefix: ["response"],
|
|
433
|
+
}), _response.rawResponse);
|
|
434
|
+
case 503:
|
|
435
|
+
throw new PredictorSDK.ServiceUnavailableError(serializers.ErrorResponse.parseOrThrow(_response.error.body, {
|
|
436
|
+
unrecognizedObjectKeys: "passthrough",
|
|
437
|
+
allowUnrecognizedUnionMembers: true,
|
|
438
|
+
allowUnrecognizedEnumValues: true,
|
|
439
|
+
skipValidation: true,
|
|
440
|
+
breadcrumbsPrefix: ["response"],
|
|
441
|
+
}), _response.rawResponse);
|
|
398
442
|
default:
|
|
399
443
|
throw new errors.PredictorSDKError({
|
|
400
444
|
statusCode: _response.error.statusCode,
|
|
@@ -423,6 +467,8 @@ export class PredictorSDKClient {
|
|
|
423
467
|
* @throws {@link PredictorSDK.TooManyRequestsError}
|
|
424
468
|
* @throws {@link PredictorSDK.BadGatewayError}
|
|
425
469
|
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
470
|
+
* @throws {@link errors.PredictorSDKError}
|
|
471
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
426
472
|
*
|
|
427
473
|
* @example
|
|
428
474
|
* await client.getMarket({
|
|
@@ -562,6 +608,8 @@ export class PredictorSDKClient {
|
|
|
562
608
|
* @throws {@link PredictorSDK.TooManyRequestsError}
|
|
563
609
|
* @throws {@link PredictorSDK.BadGatewayError}
|
|
564
610
|
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
611
|
+
* @throws {@link errors.PredictorSDKError}
|
|
612
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
565
613
|
*
|
|
566
614
|
* @example
|
|
567
615
|
* await client.getBinanceCryptoPrices({
|
|
@@ -697,6 +745,8 @@ export class PredictorSDKClient {
|
|
|
697
745
|
* @throws {@link PredictorSDK.TooManyRequestsError}
|
|
698
746
|
* @throws {@link PredictorSDK.BadGatewayError}
|
|
699
747
|
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
748
|
+
* @throws {@link errors.PredictorSDKError}
|
|
749
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
700
750
|
*
|
|
701
751
|
* @example
|
|
702
752
|
* await client.getPolymarketWallet({
|
|
@@ -839,6 +889,8 @@ export class PredictorSDKClient {
|
|
|
839
889
|
* @throws {@link PredictorSDK.TooManyRequestsError}
|
|
840
890
|
* @throws {@link PredictorSDK.BadGatewayError}
|
|
841
891
|
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
892
|
+
* @throws {@link errors.PredictorSDKError}
|
|
893
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
842
894
|
*
|
|
843
895
|
* @example
|
|
844
896
|
* await client.listPolymarketWalletPositions({
|
|
@@ -983,6 +1035,8 @@ export class PredictorSDKClient {
|
|
|
983
1035
|
* @throws {@link PredictorSDK.TooManyRequestsError}
|
|
984
1036
|
* @throws {@link PredictorSDK.BadGatewayError}
|
|
985
1037
|
* @throws {@link PredictorSDK.ServiceUnavailableError}
|
|
1038
|
+
* @throws {@link errors.PredictorSDKError}
|
|
1039
|
+
* @throws {@link errors.PredictorSDKTimeoutError}
|
|
986
1040
|
*
|
|
987
1041
|
* @example
|
|
988
1042
|
* await client.getEvent({
|
|
@@ -6,7 +6,7 @@ import type * as PredictorSDK from "../../index.js";
|
|
|
6
6
|
export interface GetMarketsRequest {
|
|
7
7
|
/** Maximum number of markets to return per page. Range 1–100, default 25. */
|
|
8
8
|
limit?: number;
|
|
9
|
-
/** Opaque cursor from a previous response's `pagination.nextCursor` in the SDKs (raw JSON: `pagination.next_cursor`). */
|
|
9
|
+
/** Opaque cursor from a previous response's `pagination.nextCursor` in the SDKs (raw JSON: `pagination.next_cursor`). Market cursors stay bound to the immutable catalog snapshot that issued them. Replaced snapshots normally remain available for up to 24 hours, but storage pressure can evict a retained snapshot sooner; retry from the first page after a stale-cursor `400`. */
|
|
10
10
|
cursor?: string;
|
|
11
11
|
/** Canonical top-level category filter. This is PredictorSDK's normalized category, not a provider-native tag. Cursors are bound to the category filter used to create them. */
|
|
12
12
|
category?: PredictorSDK.MarketCategory;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// This file was auto-generated by Fern from our API Definition.
|
|
2
|
-
/** Recommended client action for
|
|
2
|
+
/** Recommended client action for an HTTP 402 response. */
|
|
3
3
|
export const PaymentRequiredErrorAction = {
|
|
4
4
|
UpgradePlan: "upgrade_plan",
|
|
5
5
|
ResolvePayment: "resolve_payment",
|
|
@@ -7,7 +7,6 @@ export interface PaymentRequiredErrorBody {
|
|
|
7
7
|
/** Additional detail about the error. */
|
|
8
8
|
message?: string;
|
|
9
9
|
statusCode: number;
|
|
10
|
-
/** Recommended client action for this 402. */
|
|
11
10
|
action: PredictorSDK.PaymentRequiredErrorAction;
|
|
12
11
|
/** Billing tier that would satisfy the gate (e.g. `starter`, `pro`, `business`, `enterprise`). */
|
|
13
12
|
requiredTier: string;
|
|
@@ -9,6 +9,7 @@ import { getResponseBody } from "./getResponseBody.js";
|
|
|
9
9
|
import { Headers } from "./Headers.js";
|
|
10
10
|
import { makeRequest } from "./makeRequest.js";
|
|
11
11
|
import { abortRawResponse, toRawResponse, unknownRawResponse } from "./RawResponse.js";
|
|
12
|
+
import { redactUrl, SENSITIVE_QUERY_PARAMS } from "./redactUrl.js";
|
|
12
13
|
import { requestWithRetries } from "./requestWithRetries.js";
|
|
13
14
|
const SENSITIVE_HEADERS = new Set([
|
|
14
15
|
"authorization",
|
|
@@ -40,26 +41,6 @@ function redactHeaders(headers) {
|
|
|
40
41
|
}
|
|
41
42
|
return filtered;
|
|
42
43
|
}
|
|
43
|
-
const SENSITIVE_QUERY_PARAMS = new Set([
|
|
44
|
-
"api_key",
|
|
45
|
-
"api-key",
|
|
46
|
-
"apikey",
|
|
47
|
-
"token",
|
|
48
|
-
"access_token",
|
|
49
|
-
"access-token",
|
|
50
|
-
"auth_token",
|
|
51
|
-
"auth-token",
|
|
52
|
-
"password",
|
|
53
|
-
"passwd",
|
|
54
|
-
"secret",
|
|
55
|
-
"api_secret",
|
|
56
|
-
"api-secret",
|
|
57
|
-
"apisecret",
|
|
58
|
-
"key",
|
|
59
|
-
"session",
|
|
60
|
-
"session_id",
|
|
61
|
-
"session-id",
|
|
62
|
-
]);
|
|
63
44
|
function redactQueryParameters(queryParameters) {
|
|
64
45
|
if (queryParameters == null) {
|
|
65
46
|
return undefined;
|
|
@@ -70,70 +51,6 @@ function redactQueryParameters(queryParameters) {
|
|
|
70
51
|
}
|
|
71
52
|
return redacted;
|
|
72
53
|
}
|
|
73
|
-
function redactUrl(url) {
|
|
74
|
-
const protocolIndex = url.indexOf("://");
|
|
75
|
-
if (protocolIndex === -1)
|
|
76
|
-
return url;
|
|
77
|
-
const afterProtocol = protocolIndex + 3;
|
|
78
|
-
// Find the first delimiter that marks the end of the authority section
|
|
79
|
-
const pathStart = url.indexOf("/", afterProtocol);
|
|
80
|
-
let queryStart = url.indexOf("?", afterProtocol);
|
|
81
|
-
let fragmentStart = url.indexOf("#", afterProtocol);
|
|
82
|
-
const firstDelimiter = Math.min(pathStart === -1 ? url.length : pathStart, queryStart === -1 ? url.length : queryStart, fragmentStart === -1 ? url.length : fragmentStart);
|
|
83
|
-
// Find the LAST @ before the delimiter (handles multiple @ in credentials)
|
|
84
|
-
let atIndex = -1;
|
|
85
|
-
for (let i = afterProtocol; i < firstDelimiter; i++) {
|
|
86
|
-
if (url[i] === "@") {
|
|
87
|
-
atIndex = i;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
if (atIndex !== -1) {
|
|
91
|
-
url = `${url.slice(0, afterProtocol)}[REDACTED]@${url.slice(atIndex + 1)}`;
|
|
92
|
-
}
|
|
93
|
-
// Recalculate queryStart since url might have changed
|
|
94
|
-
queryStart = url.indexOf("?");
|
|
95
|
-
if (queryStart === -1)
|
|
96
|
-
return url;
|
|
97
|
-
fragmentStart = url.indexOf("#", queryStart);
|
|
98
|
-
const queryEnd = fragmentStart !== -1 ? fragmentStart : url.length;
|
|
99
|
-
const queryString = url.slice(queryStart + 1, queryEnd);
|
|
100
|
-
if (queryString.length === 0)
|
|
101
|
-
return url;
|
|
102
|
-
// FAST PATH: Quick check if any sensitive keywords present
|
|
103
|
-
// Using indexOf is faster than regex for simple substring matching
|
|
104
|
-
const lower = queryString.toLowerCase();
|
|
105
|
-
const hasSensitive = lower.includes("token") ||
|
|
106
|
-
lower.includes("key") ||
|
|
107
|
-
lower.includes("password") ||
|
|
108
|
-
lower.includes("passwd") ||
|
|
109
|
-
lower.includes("secret") ||
|
|
110
|
-
lower.includes("session") ||
|
|
111
|
-
lower.includes("auth");
|
|
112
|
-
if (!hasSensitive) {
|
|
113
|
-
return url;
|
|
114
|
-
}
|
|
115
|
-
// SLOW PATH: Parse and redact
|
|
116
|
-
const redactedParams = [];
|
|
117
|
-
const params = queryString.split("&");
|
|
118
|
-
for (const param of params) {
|
|
119
|
-
const equalIndex = param.indexOf("=");
|
|
120
|
-
if (equalIndex === -1) {
|
|
121
|
-
redactedParams.push(param);
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
const key = param.slice(0, equalIndex);
|
|
125
|
-
let shouldRedact = SENSITIVE_QUERY_PARAMS.has(key.toLowerCase());
|
|
126
|
-
if (!shouldRedact && key.includes("%")) {
|
|
127
|
-
try {
|
|
128
|
-
const decodedKey = decodeURIComponent(key);
|
|
129
|
-
shouldRedact = SENSITIVE_QUERY_PARAMS.has(decodedKey.toLowerCase());
|
|
130
|
-
}
|
|
131
|
-
catch { }
|
|
132
|
-
}
|
|
133
|
-
redactedParams.push(shouldRedact ? `${key}=[REDACTED]` : param);
|
|
134
|
-
}
|
|
135
|
-
return url.slice(0, queryStart + 1) + redactedParams.join("&") + url.slice(queryEnd);
|
|
136
|
-
}
|
|
137
54
|
async function getHeaders(args) {
|
|
138
55
|
const newHeaders = new Headers();
|
|
139
56
|
newHeaders.set("Accept", args.responseType === "json"
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { fromJson } from "../json.js";
|
|
2
2
|
import { getBinaryResponse } from "./BinaryResponse.js";
|
|
3
|
+
// Pins the upstream Response so undici's FinalizationRegistry can't GC it and cancel the body stream.
|
|
4
|
+
function retainResponse(target, response) {
|
|
5
|
+
Object.defineProperty(target, "__fern_response_ref", {
|
|
6
|
+
value: response,
|
|
7
|
+
enumerable: false,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: false,
|
|
10
|
+
});
|
|
11
|
+
}
|
|
3
12
|
export async function getResponseBody(response, responseType) {
|
|
4
13
|
switch (responseType) {
|
|
5
14
|
case "binary-response":
|
|
@@ -18,6 +27,7 @@ export async function getResponseBody(response, responseType) {
|
|
|
18
27
|
},
|
|
19
28
|
};
|
|
20
29
|
}
|
|
30
|
+
retainResponse(response.body, response);
|
|
21
31
|
return response.body;
|
|
22
32
|
case "streaming":
|
|
23
33
|
if (response.body == null) {
|
|
@@ -29,6 +39,7 @@ export async function getResponseBody(response, responseType) {
|
|
|
29
39
|
},
|
|
30
40
|
};
|
|
31
41
|
}
|
|
42
|
+
retainResponse(response.body, response);
|
|
32
43
|
return response.body;
|
|
33
44
|
case "text":
|
|
34
45
|
return await response.text();
|
|
@@ -3,6 +3,7 @@ import { join } from "../url/join.js";
|
|
|
3
3
|
import { EndpointSupplier } from "./EndpointSupplier.js";
|
|
4
4
|
import { getFetchFn } from "./getFetchFn.js";
|
|
5
5
|
import { makeRequest } from "./makeRequest.js";
|
|
6
|
+
import { redactUrl } from "./redactUrl.js";
|
|
6
7
|
import { requestWithRetries } from "./requestWithRetries.js";
|
|
7
8
|
import { Supplier } from "./Supplier.js";
|
|
8
9
|
/**
|
|
@@ -66,8 +67,10 @@ export async function makePassthroughRequest(input, init, clientOptions, request
|
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
|
-
// Apply auth headers
|
|
70
|
-
|
|
70
|
+
// Apply auth headers, but only when the resolved URL targets the configured base URL.
|
|
71
|
+
// This prevents the SDK's credentials from leaking to an unrelated host when a caller
|
|
72
|
+
// passes an absolute cross-origin URL into the passthrough fetch escape hatch.
|
|
73
|
+
if (clientOptions.getAuthHeaders != null && targetsBaseUrl(fullUrl, baseUrl)) {
|
|
71
74
|
const authHeaders = await clientOptions.getAuthHeaders();
|
|
72
75
|
for (const [key, value] of Object.entries(authHeaders)) {
|
|
73
76
|
mergedHeaders[key.toLowerCase()] = value;
|
|
@@ -102,7 +105,7 @@ export async function makePassthroughRequest(input, init, clientOptions, request
|
|
|
102
105
|
if (logger.isDebug()) {
|
|
103
106
|
logger.debug("Making passthrough HTTP request", {
|
|
104
107
|
method,
|
|
105
|
-
url: fullUrl,
|
|
108
|
+
url: redactUrl(fullUrl),
|
|
106
109
|
hasBody: body != null,
|
|
107
110
|
});
|
|
108
111
|
}
|
|
@@ -111,9 +114,28 @@ export async function makePassthroughRequest(input, init, clientOptions, request
|
|
|
111
114
|
if (logger.isDebug()) {
|
|
112
115
|
logger.debug("Passthrough HTTP request completed", {
|
|
113
116
|
method,
|
|
114
|
-
url: fullUrl,
|
|
117
|
+
url: redactUrl(fullUrl),
|
|
115
118
|
statusCode: response.status,
|
|
116
119
|
});
|
|
117
120
|
}
|
|
118
121
|
return response;
|
|
119
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Returns true when the resolved request URL points at the same origin as the
|
|
125
|
+
* configured base URL. Relative paths are always joined onto the base URL, so
|
|
126
|
+
* they resolve to the base origin and return true. Absolute URLs only match when
|
|
127
|
+
* their origin equals the base origin. When there is no base URL to compare
|
|
128
|
+
* against, or either value is not a parseable absolute URL, this returns false so
|
|
129
|
+
* auth headers are not attached.
|
|
130
|
+
*/
|
|
131
|
+
function targetsBaseUrl(fullUrl, baseUrl) {
|
|
132
|
+
if (baseUrl == null) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
return new URL(fullUrl).origin === new URL(baseUrl).origin;
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export const SENSITIVE_QUERY_PARAMS = new Set([
|
|
2
|
+
"api_key",
|
|
3
|
+
"api-key",
|
|
4
|
+
"apikey",
|
|
5
|
+
"token",
|
|
6
|
+
"access_token",
|
|
7
|
+
"access-token",
|
|
8
|
+
"auth_token",
|
|
9
|
+
"auth-token",
|
|
10
|
+
"password",
|
|
11
|
+
"passwd",
|
|
12
|
+
"secret",
|
|
13
|
+
"api_secret",
|
|
14
|
+
"api-secret",
|
|
15
|
+
"apisecret",
|
|
16
|
+
"key",
|
|
17
|
+
"session",
|
|
18
|
+
"session_id",
|
|
19
|
+
"session-id",
|
|
20
|
+
]);
|
|
21
|
+
export function redactUrl(url) {
|
|
22
|
+
const protocolIndex = url.indexOf("://");
|
|
23
|
+
if (protocolIndex === -1)
|
|
24
|
+
return url;
|
|
25
|
+
const afterProtocol = protocolIndex + 3;
|
|
26
|
+
// Find the first delimiter that marks the end of the authority section
|
|
27
|
+
const pathStart = url.indexOf("/", afterProtocol);
|
|
28
|
+
let queryStart = url.indexOf("?", afterProtocol);
|
|
29
|
+
let fragmentStart = url.indexOf("#", afterProtocol);
|
|
30
|
+
const firstDelimiter = Math.min(pathStart === -1 ? url.length : pathStart, queryStart === -1 ? url.length : queryStart, fragmentStart === -1 ? url.length : fragmentStart);
|
|
31
|
+
// Find the LAST @ before the delimiter (handles multiple @ in credentials)
|
|
32
|
+
let atIndex = -1;
|
|
33
|
+
for (let i = afterProtocol; i < firstDelimiter; i++) {
|
|
34
|
+
if (url[i] === "@") {
|
|
35
|
+
atIndex = i;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (atIndex !== -1) {
|
|
39
|
+
url = `${url.slice(0, afterProtocol)}[REDACTED]@${url.slice(atIndex + 1)}`;
|
|
40
|
+
}
|
|
41
|
+
// Recalculate queryStart since url might have changed
|
|
42
|
+
queryStart = url.indexOf("?");
|
|
43
|
+
if (queryStart === -1)
|
|
44
|
+
return url;
|
|
45
|
+
fragmentStart = url.indexOf("#", queryStart);
|
|
46
|
+
const queryEnd = fragmentStart !== -1 ? fragmentStart : url.length;
|
|
47
|
+
const queryString = url.slice(queryStart + 1, queryEnd);
|
|
48
|
+
if (queryString.length === 0)
|
|
49
|
+
return url;
|
|
50
|
+
// FAST PATH: Quick check if any sensitive keywords present
|
|
51
|
+
// Using indexOf is faster than regex for simple substring matching
|
|
52
|
+
const lower = queryString.toLowerCase();
|
|
53
|
+
const hasSensitive = lower.includes("token") ||
|
|
54
|
+
lower.includes("key") ||
|
|
55
|
+
lower.includes("password") ||
|
|
56
|
+
lower.includes("passwd") ||
|
|
57
|
+
lower.includes("secret") ||
|
|
58
|
+
lower.includes("session") ||
|
|
59
|
+
lower.includes("auth");
|
|
60
|
+
if (!hasSensitive) {
|
|
61
|
+
return url;
|
|
62
|
+
}
|
|
63
|
+
// SLOW PATH: Parse and redact
|
|
64
|
+
const redactedParams = [];
|
|
65
|
+
const params = queryString.split("&");
|
|
66
|
+
for (const param of params) {
|
|
67
|
+
const equalIndex = param.indexOf("=");
|
|
68
|
+
if (equalIndex === -1) {
|
|
69
|
+
redactedParams.push(param);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const key = param.slice(0, equalIndex);
|
|
73
|
+
let shouldRedact = SENSITIVE_QUERY_PARAMS.has(key.toLowerCase());
|
|
74
|
+
if (!shouldRedact && key.includes("%")) {
|
|
75
|
+
try {
|
|
76
|
+
const decodedKey = decodeURIComponent(key);
|
|
77
|
+
shouldRedact = SENSITIVE_QUERY_PARAMS.has(decodedKey.toLowerCase());
|
|
78
|
+
}
|
|
79
|
+
catch { }
|
|
80
|
+
}
|
|
81
|
+
redactedParams.push(shouldRedact ? `${key}=[REDACTED]` : param);
|
|
82
|
+
}
|
|
83
|
+
return url.slice(0, queryStart + 1) + redactedParams.join("&") + url.slice(queryEnd);
|
|
84
|
+
}
|
|
@@ -35,11 +35,11 @@ export function getRetryDelayFromHeaders(response, retryAttempt) {
|
|
|
35
35
|
const resetTimeMilliseconds = resetTime >= 1_000_000_000_000 ? resetTime : resetTime * 1000;
|
|
36
36
|
const delay = resetTimeMilliseconds - Date.now();
|
|
37
37
|
if (delay > 0) {
|
|
38
|
-
return addPositiveJitter(Math.min(delay, MAX_RETRY_DELAY));
|
|
38
|
+
return Math.min(addPositiveJitter(Math.min(delay, MAX_RETRY_DELAY)), MAX_RETRY_DELAY);
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
return addSymmetricJitter(Math.min(INITIAL_RETRY_DELAY * 2 ** retryAttempt, MAX_RETRY_DELAY));
|
|
42
|
+
return Math.min(addSymmetricJitter(Math.min(INITIAL_RETRY_DELAY * 2 ** retryAttempt, MAX_RETRY_DELAY)), MAX_RETRY_DELAY);
|
|
43
43
|
}
|
|
44
44
|
export async function requestWithRetries(requestFn, maxRetries = DEFAULT_MAX_RETRIES) {
|
|
45
45
|
let response = await requestFn();
|
|
@@ -10,11 +10,19 @@ export function anySignal(...args) {
|
|
|
10
10
|
for (const signal of signals) {
|
|
11
11
|
if (signal.aborted) {
|
|
12
12
|
controller.abort(signal?.reason);
|
|
13
|
-
|
|
13
|
+
return controller.signal;
|
|
14
14
|
}
|
|
15
15
|
signal.addEventListener("abort", () => controller.abort(signal?.reason), {
|
|
16
16
|
signal: controller.signal,
|
|
17
17
|
});
|
|
18
|
+
// Re-check after adding listener: the signal may have aborted
|
|
19
|
+
// between the initial `signal.aborted` check and the `addEventListener`
|
|
20
|
+
// call above. If it did, the abort event was already dispatched and
|
|
21
|
+
// the listener will never fire — we must manually abort.
|
|
22
|
+
if (signal.aborted) {
|
|
23
|
+
controller.abort(signal?.reason);
|
|
24
|
+
return controller.signal;
|
|
25
|
+
}
|
|
18
26
|
}
|
|
19
27
|
return controller.signal;
|
|
20
28
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spreads caller-supplied `additionalBodyParameters` (from `requestOptions.additionalBodyParameters`)
|
|
3
|
+
* on top of the request body. Caller-supplied properties win over the endpoint body. When no
|
|
4
|
+
* additional body parameters are provided, the original body is returned unchanged so serialization
|
|
5
|
+
* is unaffected.
|
|
6
|
+
*
|
|
7
|
+
* The merge only applies to plain-object (JSON object) bodies. When the body is `null`/`undefined`
|
|
8
|
+
* the additional parameters become the body; when the body is an array or a primitive JSON value it
|
|
9
|
+
* is returned unchanged, since object properties cannot be spread into it. This mirrors the Python
|
|
10
|
+
* SDK, which only merges additional body parameters into mapping bodies.
|
|
11
|
+
*/
|
|
12
|
+
export declare function mergeAdditionalBodyParameters(body: unknown, additionalBodyParameters: Record<string, unknown> | undefined): unknown;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spreads caller-supplied `additionalBodyParameters` (from `requestOptions.additionalBodyParameters`)
|
|
3
|
+
* on top of the request body. Caller-supplied properties win over the endpoint body. When no
|
|
4
|
+
* additional body parameters are provided, the original body is returned unchanged so serialization
|
|
5
|
+
* is unaffected.
|
|
6
|
+
*
|
|
7
|
+
* The merge only applies to plain-object (JSON object) bodies. When the body is `null`/`undefined`
|
|
8
|
+
* the additional parameters become the body; when the body is an array or a primitive JSON value it
|
|
9
|
+
* is returned unchanged, since object properties cannot be spread into it. This mirrors the Python
|
|
10
|
+
* SDK, which only merges additional body parameters into mapping bodies.
|
|
11
|
+
*/
|
|
12
|
+
export function mergeAdditionalBodyParameters(body, additionalBodyParameters) {
|
|
13
|
+
if (additionalBodyParameters == null) {
|
|
14
|
+
return body;
|
|
15
|
+
}
|
|
16
|
+
if (body == null) {
|
|
17
|
+
return { ...additionalBodyParameters };
|
|
18
|
+
}
|
|
19
|
+
if (typeof body === "object" && !Array.isArray(body)) {
|
|
20
|
+
return { ...body, ...additionalBodyParameters };
|
|
21
|
+
}
|
|
22
|
+
return body;
|
|
23
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { RUNTIME } from "./runtime.js";
|
|
1
|
+
export { getUserAgent, RUNTIME } from "./runtime.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { RUNTIME } from "./runtime.js";
|
|
1
|
+
export { getUserAgent, RUNTIME } from "./runtime.js";
|
|
@@ -6,4 +6,23 @@ export interface Runtime {
|
|
|
6
6
|
type: "browser" | "web-worker" | "deno" | "bun" | "node" | "react-native" | "unknown" | "workerd" | "edge-runtime";
|
|
7
7
|
version?: string;
|
|
8
8
|
parsedVersion?: number;
|
|
9
|
+
/**
|
|
10
|
+
* The operating system the SDK is running on, when it can be determined
|
|
11
|
+
* (e.g. "linux", "darwin", "win32" on server runtimes). Undefined in
|
|
12
|
+
* environments where the OS is not observable (e.g. browsers).
|
|
13
|
+
*/
|
|
14
|
+
os?: string;
|
|
15
|
+
/**
|
|
16
|
+
* The CPU architecture the SDK is running on, when it can be determined
|
|
17
|
+
* (e.g. "x64", "arm64" on server runtimes). Undefined in environments where
|
|
18
|
+
* the architecture is not observable (e.g. browsers).
|
|
19
|
+
*/
|
|
20
|
+
arch?: string;
|
|
9
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Builds a structured User-Agent string of the form
|
|
24
|
+
* `{sdkName}/{sdkVersion} ({os}; {arch}) {runtime}/{runtimeVersion}`
|
|
25
|
+
* where the platform group and runtime segment are omitted gracefully when the
|
|
26
|
+
* underlying values cannot be determined (e.g. in a browser).
|
|
27
|
+
*/
|
|
28
|
+
export declare function getUserAgent(sdkName: string, sdkVersion: string): string;
|
|
@@ -55,6 +55,8 @@ function evaluateRuntime() {
|
|
|
55
55
|
return {
|
|
56
56
|
type: "deno",
|
|
57
57
|
version: Deno.version.deno,
|
|
58
|
+
os: Deno.build?.os,
|
|
59
|
+
arch: Deno.build?.arch,
|
|
58
60
|
};
|
|
59
61
|
}
|
|
60
62
|
/**
|
|
@@ -65,6 +67,8 @@ function evaluateRuntime() {
|
|
|
65
67
|
return {
|
|
66
68
|
type: "bun",
|
|
67
69
|
version: Bun.version,
|
|
70
|
+
os: typeof process !== "undefined" ? process.platform : undefined,
|
|
71
|
+
arch: typeof process !== "undefined" ? process.arch : undefined,
|
|
68
72
|
};
|
|
69
73
|
}
|
|
70
74
|
/**
|
|
@@ -92,9 +96,76 @@ function evaluateRuntime() {
|
|
|
92
96
|
type: "node",
|
|
93
97
|
version: _process.versions.node,
|
|
94
98
|
parsedVersion: Number(_process.versions.node.split(".")[0]),
|
|
99
|
+
os: _process.platform,
|
|
100
|
+
arch: _process.arch,
|
|
95
101
|
};
|
|
96
102
|
}
|
|
97
103
|
return {
|
|
98
104
|
type: "unknown",
|
|
99
105
|
};
|
|
100
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Display names for the language runtimes whose version is meaningful to encode
|
|
109
|
+
* in a User-Agent. Environments where a version string is not useful (e.g.
|
|
110
|
+
* browsers, where `version` is the full navigator UA) are intentionally mapped
|
|
111
|
+
* to `undefined` so they are omitted from the User-Agent.
|
|
112
|
+
*/
|
|
113
|
+
const RUNTIME_DISPLAY_NAMES = {
|
|
114
|
+
node: "Node",
|
|
115
|
+
deno: "Deno",
|
|
116
|
+
bun: "Bun",
|
|
117
|
+
browser: undefined,
|
|
118
|
+
"web-worker": undefined,
|
|
119
|
+
"react-native": undefined,
|
|
120
|
+
workerd: undefined,
|
|
121
|
+
"edge-runtime": undefined,
|
|
122
|
+
unknown: undefined,
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* CPU architecture aliases that all refer to 64-bit x86. They are normalized to
|
|
126
|
+
* the single canonical token `x86_64` so the User-Agent architecture label is
|
|
127
|
+
* consistent regardless of which runtime reports it (Node reports `x64`, others
|
|
128
|
+
* report `amd64` or `x86_64`).
|
|
129
|
+
*/
|
|
130
|
+
const X86_64_ARCH_ALIASES = new Set(["x64", "amd64", "x86_64"]);
|
|
131
|
+
/**
|
|
132
|
+
* Normalizes a CPU architecture token, collapsing the 64-bit x86 aliases
|
|
133
|
+
* (`x64`, `amd64`, `x86_64`) to `x86_64`. Other architectures are returned
|
|
134
|
+
* unchanged.
|
|
135
|
+
*/
|
|
136
|
+
function normalizeArch(arch) {
|
|
137
|
+
if (arch == null) {
|
|
138
|
+
return arch;
|
|
139
|
+
}
|
|
140
|
+
return X86_64_ARCH_ALIASES.has(arch.toLowerCase()) ? "x86_64" : arch;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Percent-encodes the `@` and `/` characters in an npm package name so the
|
|
144
|
+
* User-Agent product token stays within the RFC 7230 token grammar. The
|
|
145
|
+
* original scoped package name can be recovered by URL-decoding (e.g.
|
|
146
|
+
* `@dummy/sdk` becomes `%40dummy%2Fsdk`).
|
|
147
|
+
*/
|
|
148
|
+
function encodeProductName(sdkName) {
|
|
149
|
+
return sdkName.replace(/@/g, "%40").replace(/\//g, "%2F");
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Builds a structured User-Agent string of the form
|
|
153
|
+
* `{sdkName}/{sdkVersion} ({os}; {arch}) {runtime}/{runtimeVersion}`
|
|
154
|
+
* where the platform group and runtime segment are omitted gracefully when the
|
|
155
|
+
* underlying values cannot be determined (e.g. in a browser).
|
|
156
|
+
*/
|
|
157
|
+
export function getUserAgent(sdkName, sdkVersion) {
|
|
158
|
+
let userAgent = `${encodeProductName(sdkName)}/${sdkVersion}`;
|
|
159
|
+
const platform = [RUNTIME.os, normalizeArch(RUNTIME.arch)].filter((part) => part != null && part.length > 0);
|
|
160
|
+
if (platform.length > 0) {
|
|
161
|
+
userAgent += ` (${platform.join("; ")})`;
|
|
162
|
+
}
|
|
163
|
+
const runtimeName = RUNTIME_DISPLAY_NAMES[RUNTIME.type];
|
|
164
|
+
if (runtimeName != null) {
|
|
165
|
+
userAgent += ` ${runtimeName}`;
|
|
166
|
+
if (RUNTIME.version != null && RUNTIME.version.length > 0) {
|
|
167
|
+
userAgent += `/${RUNTIME.version}`;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return userAgent;
|
|
171
|
+
}
|
|
@@ -4,7 +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,
|
|
8
|
-
this.name =
|
|
7
|
+
Object.setPrototypeOf(this, JsonError.prototype);
|
|
8
|
+
this.name = "JsonError";
|
|
9
9
|
}
|
|
10
10
|
}
|
|
@@ -4,7 +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,
|
|
8
|
-
this.name =
|
|
7
|
+
Object.setPrototypeOf(this, ParseError.prototype);
|
|
8
|
+
this.name = "ParseError";
|
|
9
9
|
}
|
|
10
10
|
}
|
package/dist/core/url/qs.js
CHANGED
|
@@ -16,7 +16,7 @@ function stringifyObject(obj, prefix = "", options) {
|
|
|
16
16
|
const parts = [];
|
|
17
17
|
for (const [key, value] of Object.entries(obj)) {
|
|
18
18
|
const fullKey = prefix ? `${prefix}[${key}]` : key;
|
|
19
|
-
if (value
|
|
19
|
+
if (value == null) {
|
|
20
20
|
continue;
|
|
21
21
|
}
|
|
22
22
|
if (Array.isArray(value)) {
|
|
@@ -36,7 +36,7 @@ function stringifyObject(obj, prefix = "", options) {
|
|
|
36
36
|
else {
|
|
37
37
|
for (let i = 0; i < value.length; i++) {
|
|
38
38
|
const item = value[i];
|
|
39
|
-
if (item
|
|
39
|
+
if (item == null) {
|
|
40
40
|
continue;
|
|
41
41
|
}
|
|
42
42
|
if (typeof item === "object" && !Array.isArray(item) && item !== null) {
|
|
@@ -11,7 +11,7 @@ export class PredictorSDKError extends Error {
|
|
|
11
11
|
if (Error.captureStackTrace) {
|
|
12
12
|
Error.captureStackTrace(this, this.constructor);
|
|
13
13
|
}
|
|
14
|
-
this.name =
|
|
14
|
+
this.name = "PredictorSDKError";
|
|
15
15
|
this.statusCode = statusCode;
|
|
16
16
|
this.body = body;
|
|
17
17
|
this.rawResponse = rawResponse;
|
|
@@ -19,6 +19,9 @@ export class PredictorSDKError extends Error {
|
|
|
19
19
|
this.cause = cause;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
+
get requestId() {
|
|
23
|
+
return this.rawResponse?.headers?.get("x-request-id") ?? undefined;
|
|
24
|
+
}
|
|
22
25
|
}
|
|
23
26
|
function buildMessage({ message, statusCode, body, }) {
|
|
24
27
|
const lines = [];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import * as errors from "./index.js";
|
|
2
|
+
export declare class PredictorSDKTimeoutError extends errors.PredictorSDKError {
|
|
3
3
|
constructor(message: string, opts?: {
|
|
4
4
|
cause?: unknown;
|
|
5
5
|
});
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
// This file was auto-generated by Fern from our API Definition.
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import * as errors from "./index.js";
|
|
3
|
+
export class PredictorSDKTimeoutError extends errors.PredictorSDKError {
|
|
4
4
|
constructor(message, opts) {
|
|
5
|
-
super(
|
|
5
|
+
super({
|
|
6
|
+
message: message,
|
|
7
|
+
cause: opts?.cause,
|
|
8
|
+
});
|
|
6
9
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
7
10
|
if (Error.captureStackTrace) {
|
|
8
11
|
Error.captureStackTrace(this, this.constructor);
|
|
9
12
|
}
|
|
10
|
-
this.name =
|
|
11
|
-
if (opts?.cause != null) {
|
|
12
|
-
this.cause = opts.cause;
|
|
13
|
-
}
|
|
13
|
+
this.name = "PredictorSDKTimeoutError";
|
|
14
14
|
}
|
|
15
15
|
}
|