@getanyapi/sdk 0.9.7 → 0.9.9
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 +31 -8
- package/dist/index.cjs +60 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -6
- package/dist/index.d.ts +28 -6
- package/dist/index.js +60 -84
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -8,8 +8,11 @@ interface RunResult<T> {
|
|
|
8
8
|
provider: "AnyAPI";
|
|
9
9
|
/** Amount charged in USD for this call. */
|
|
10
10
|
costUsd: number;
|
|
11
|
-
/**
|
|
12
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Number of result rows returned. Always present on the wire: the gateway's field
|
|
13
|
+
* carries no `omitempty`, and a metadata-only replay preserves the original count.
|
|
14
|
+
*/
|
|
15
|
+
items: number;
|
|
13
16
|
/**
|
|
14
17
|
* True when the gateway served a stored response for a repeated Idempotency-Key instead
|
|
15
18
|
* of running the SKU again. A replay is not billed twice. Always present on the wire.
|
|
@@ -55,8 +58,11 @@ interface BareRunResult<T> {
|
|
|
55
58
|
provider: "AnyAPI";
|
|
56
59
|
/** Amount charged in USD for this call. */
|
|
57
60
|
costUsd: number;
|
|
58
|
-
/**
|
|
59
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Number of result rows returned. Always present on the wire: the gateway's field
|
|
63
|
+
* carries no `omitempty`, and a metadata-only replay preserves the original count.
|
|
64
|
+
*/
|
|
65
|
+
items: number;
|
|
60
66
|
/**
|
|
61
67
|
* True when the gateway served a stored response for a repeated Idempotency-Key instead
|
|
62
68
|
* of running the SKU again. A replay is not billed twice. Always present on the wire.
|
|
@@ -108,6 +114,8 @@ interface RequestOptions {
|
|
|
108
114
|
signal?: AbortSignal;
|
|
109
115
|
/** Override the client maxRetries for this call. */
|
|
110
116
|
maxRetries?: number;
|
|
117
|
+
/** Override the client maxInProgressWaitMs for this call. */
|
|
118
|
+
maxInProgressWaitMs?: number;
|
|
111
119
|
/** Override the generated Idempotency-Key for this billed POST. */
|
|
112
120
|
idempotencyKey?: string;
|
|
113
121
|
}
|
|
@@ -127,6 +135,13 @@ interface ClientOptions {
|
|
|
127
135
|
timeoutMs?: number;
|
|
128
136
|
/** Send Idempotency-Key on billed POSTs. Default "auto"; use "off" as a kill switch. */
|
|
129
137
|
idempotency?: "auto" | "off";
|
|
138
|
+
/**
|
|
139
|
+
* Total milliseconds one run() call may block waiting out a 409 `idempotency_in_progress`
|
|
140
|
+
* (the gateway is still executing the run this key claims). Default 60000. Set 0 to
|
|
141
|
+
* surface that 409 immediately. This is a whole-call budget across every in-progress
|
|
142
|
+
* wait, separate from the 8000ms ordinary-backoff ceiling.
|
|
143
|
+
*/
|
|
144
|
+
maxInProgressWaitMs?: number;
|
|
130
145
|
}
|
|
131
146
|
/**
|
|
132
147
|
* Account profile returned by /v1/me (internal-only fields dropped). See SPEC 2.7.
|
|
@@ -162,7 +177,7 @@ interface DiscoveryPricing {
|
|
|
162
177
|
failoverMaxUsd: number;
|
|
163
178
|
}
|
|
164
179
|
interface LaneHealth {
|
|
165
|
-
window:
|
|
180
|
+
window: string;
|
|
166
181
|
uptimePct: number;
|
|
167
182
|
latencyP50Ms: number;
|
|
168
183
|
requests: number;
|
|
@@ -183,6 +198,8 @@ interface CatalogEntry {
|
|
|
183
198
|
lanes: DiscoveryLane[];
|
|
184
199
|
heavy: boolean;
|
|
185
200
|
tryEligible: boolean;
|
|
201
|
+
failover?: boolean;
|
|
202
|
+
excludesCallerDelay?: boolean;
|
|
186
203
|
inputSchema?: Record<string, unknown>;
|
|
187
204
|
outputSchema?: Record<string, unknown>;
|
|
188
205
|
}
|
|
@@ -257,6 +274,7 @@ declare class AnyAPI$1 implements ClientCore {
|
|
|
257
274
|
private readonly maxRetries;
|
|
258
275
|
private readonly timeoutMs;
|
|
259
276
|
private readonly idempotency;
|
|
277
|
+
private readonly maxInProgressWaitMs;
|
|
260
278
|
/**
|
|
261
279
|
* The network seam the generated per-platform namespaces target. The base client IS a
|
|
262
280
|
* ClientCore (it implements `run`), so the generated subclass hands `this._core` to each
|
|
@@ -292,6 +310,7 @@ declare class AnyAPI$1 implements ClientCore {
|
|
|
292
310
|
body?: string;
|
|
293
311
|
timeoutMs: number;
|
|
294
312
|
maxRetries: number;
|
|
313
|
+
maxInProgressWaitMs?: number;
|
|
295
314
|
signal?: AbortSignal;
|
|
296
315
|
idempotencyKey?: string;
|
|
297
316
|
}): Promise<T>;
|
|
@@ -337,7 +356,10 @@ declare function paginate<Item, Page extends RunResult<unknown> | BareRunResult<
|
|
|
337
356
|
declare class AnyAPIError extends Error {
|
|
338
357
|
/** HTTP status code, or 0 for transport-level failures (connection/timeout). */
|
|
339
358
|
readonly status: number;
|
|
340
|
-
/**
|
|
359
|
+
/**
|
|
360
|
+
* The gateway's X-Anyapi-Request-Id response header when present (falling back to a
|
|
361
|
+
* proxy-set x-request-id), else undefined. Quote it to AnyAPI support.
|
|
362
|
+
*/
|
|
341
363
|
readonly requestId?: string;
|
|
342
364
|
/** Stable gateway error code when the JSON body includes one, else undefined. */
|
|
343
365
|
readonly code?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -8,8 +8,11 @@ interface RunResult<T> {
|
|
|
8
8
|
provider: "AnyAPI";
|
|
9
9
|
/** Amount charged in USD for this call. */
|
|
10
10
|
costUsd: number;
|
|
11
|
-
/**
|
|
12
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Number of result rows returned. Always present on the wire: the gateway's field
|
|
13
|
+
* carries no `omitempty`, and a metadata-only replay preserves the original count.
|
|
14
|
+
*/
|
|
15
|
+
items: number;
|
|
13
16
|
/**
|
|
14
17
|
* True when the gateway served a stored response for a repeated Idempotency-Key instead
|
|
15
18
|
* of running the SKU again. A replay is not billed twice. Always present on the wire.
|
|
@@ -55,8 +58,11 @@ interface BareRunResult<T> {
|
|
|
55
58
|
provider: "AnyAPI";
|
|
56
59
|
/** Amount charged in USD for this call. */
|
|
57
60
|
costUsd: number;
|
|
58
|
-
/**
|
|
59
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Number of result rows returned. Always present on the wire: the gateway's field
|
|
63
|
+
* carries no `omitempty`, and a metadata-only replay preserves the original count.
|
|
64
|
+
*/
|
|
65
|
+
items: number;
|
|
60
66
|
/**
|
|
61
67
|
* True when the gateway served a stored response for a repeated Idempotency-Key instead
|
|
62
68
|
* of running the SKU again. A replay is not billed twice. Always present on the wire.
|
|
@@ -108,6 +114,8 @@ interface RequestOptions {
|
|
|
108
114
|
signal?: AbortSignal;
|
|
109
115
|
/** Override the client maxRetries for this call. */
|
|
110
116
|
maxRetries?: number;
|
|
117
|
+
/** Override the client maxInProgressWaitMs for this call. */
|
|
118
|
+
maxInProgressWaitMs?: number;
|
|
111
119
|
/** Override the generated Idempotency-Key for this billed POST. */
|
|
112
120
|
idempotencyKey?: string;
|
|
113
121
|
}
|
|
@@ -127,6 +135,13 @@ interface ClientOptions {
|
|
|
127
135
|
timeoutMs?: number;
|
|
128
136
|
/** Send Idempotency-Key on billed POSTs. Default "auto"; use "off" as a kill switch. */
|
|
129
137
|
idempotency?: "auto" | "off";
|
|
138
|
+
/**
|
|
139
|
+
* Total milliseconds one run() call may block waiting out a 409 `idempotency_in_progress`
|
|
140
|
+
* (the gateway is still executing the run this key claims). Default 60000. Set 0 to
|
|
141
|
+
* surface that 409 immediately. This is a whole-call budget across every in-progress
|
|
142
|
+
* wait, separate from the 8000ms ordinary-backoff ceiling.
|
|
143
|
+
*/
|
|
144
|
+
maxInProgressWaitMs?: number;
|
|
130
145
|
}
|
|
131
146
|
/**
|
|
132
147
|
* Account profile returned by /v1/me (internal-only fields dropped). See SPEC 2.7.
|
|
@@ -162,7 +177,7 @@ interface DiscoveryPricing {
|
|
|
162
177
|
failoverMaxUsd: number;
|
|
163
178
|
}
|
|
164
179
|
interface LaneHealth {
|
|
165
|
-
window:
|
|
180
|
+
window: string;
|
|
166
181
|
uptimePct: number;
|
|
167
182
|
latencyP50Ms: number;
|
|
168
183
|
requests: number;
|
|
@@ -183,6 +198,8 @@ interface CatalogEntry {
|
|
|
183
198
|
lanes: DiscoveryLane[];
|
|
184
199
|
heavy: boolean;
|
|
185
200
|
tryEligible: boolean;
|
|
201
|
+
failover?: boolean;
|
|
202
|
+
excludesCallerDelay?: boolean;
|
|
186
203
|
inputSchema?: Record<string, unknown>;
|
|
187
204
|
outputSchema?: Record<string, unknown>;
|
|
188
205
|
}
|
|
@@ -257,6 +274,7 @@ declare class AnyAPI$1 implements ClientCore {
|
|
|
257
274
|
private readonly maxRetries;
|
|
258
275
|
private readonly timeoutMs;
|
|
259
276
|
private readonly idempotency;
|
|
277
|
+
private readonly maxInProgressWaitMs;
|
|
260
278
|
/**
|
|
261
279
|
* The network seam the generated per-platform namespaces target. The base client IS a
|
|
262
280
|
* ClientCore (it implements `run`), so the generated subclass hands `this._core` to each
|
|
@@ -292,6 +310,7 @@ declare class AnyAPI$1 implements ClientCore {
|
|
|
292
310
|
body?: string;
|
|
293
311
|
timeoutMs: number;
|
|
294
312
|
maxRetries: number;
|
|
313
|
+
maxInProgressWaitMs?: number;
|
|
295
314
|
signal?: AbortSignal;
|
|
296
315
|
idempotencyKey?: string;
|
|
297
316
|
}): Promise<T>;
|
|
@@ -337,7 +356,10 @@ declare function paginate<Item, Page extends RunResult<unknown> | BareRunResult<
|
|
|
337
356
|
declare class AnyAPIError extends Error {
|
|
338
357
|
/** HTTP status code, or 0 for transport-level failures (connection/timeout). */
|
|
339
358
|
readonly status: number;
|
|
340
|
-
/**
|
|
359
|
+
/**
|
|
360
|
+
* The gateway's X-Anyapi-Request-Id response header when present (falling back to a
|
|
361
|
+
* proxy-set x-request-id), else undefined. Quote it to AnyAPI support.
|
|
362
|
+
*/
|
|
341
363
|
readonly requestId?: string;
|
|
342
364
|
/** Stable gateway error code when the JSON body includes one, else undefined. */
|
|
343
365
|
readonly code?: string;
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
var AnyAPIError = class extends Error {
|
|
3
3
|
/** HTTP status code, or 0 for transport-level failures (connection/timeout). */
|
|
4
4
|
status;
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* The gateway's X-Anyapi-Request-Id response header when present (falling back to a
|
|
7
|
+
* proxy-set x-request-id), else undefined. Quote it to AnyAPI support.
|
|
8
|
+
*/
|
|
6
9
|
requestId;
|
|
7
10
|
/** Stable gateway error code when the JSON body includes one, else undefined. */
|
|
8
11
|
code;
|
|
@@ -37,6 +40,14 @@ var ConnectionError = class extends AnyAPIError {
|
|
|
37
40
|
};
|
|
38
41
|
var TimeoutError = class extends AnyAPIError {
|
|
39
42
|
};
|
|
43
|
+
var REQUEST_ID_HEADERS = ["x-anyapi-request-id", "x-request-id"];
|
|
44
|
+
function requestIdOf(headers) {
|
|
45
|
+
for (const name of REQUEST_ID_HEADERS) {
|
|
46
|
+
const value = headers.get(name);
|
|
47
|
+
if (value) return value;
|
|
48
|
+
}
|
|
49
|
+
return void 0;
|
|
50
|
+
}
|
|
40
51
|
function errorFromStatus(status, message, requestId, code) {
|
|
41
52
|
switch (status) {
|
|
42
53
|
case 400:
|
|
@@ -108,17 +119,20 @@ var DEFAULT_BASE_URL = "https://api.getanyapi.com";
|
|
|
108
119
|
function malformed(path) {
|
|
109
120
|
throw new AnyAPIError(`malformed discovery response: ${path}`, 0);
|
|
110
121
|
}
|
|
111
|
-
function
|
|
122
|
+
function rejectUnsafeDiscoveryFields(value, path) {
|
|
112
123
|
if (Array.isArray(value)) {
|
|
113
124
|
value.forEach(
|
|
114
|
-
(item, index) =>
|
|
125
|
+
(item, index) => rejectUnsafeDiscoveryFields(item, `${path}[${index}]`)
|
|
115
126
|
);
|
|
116
127
|
return;
|
|
117
128
|
}
|
|
118
129
|
if (typeof value !== "object" || value === null) return;
|
|
119
130
|
for (const [key, item] of Object.entries(value)) {
|
|
120
131
|
if (key.toLowerCase().includes("credit")) malformed(`${path}.${key}`);
|
|
121
|
-
|
|
132
|
+
if (key === "provider" && item !== "AnyAPI") {
|
|
133
|
+
malformed(`${path}.${key}`);
|
|
134
|
+
}
|
|
135
|
+
rejectUnsafeDiscoveryFields(item, `${path}.${key}`);
|
|
122
136
|
}
|
|
123
137
|
}
|
|
124
138
|
function record(value, path) {
|
|
@@ -127,12 +141,6 @@ function record(value, path) {
|
|
|
127
141
|
}
|
|
128
142
|
return value;
|
|
129
143
|
}
|
|
130
|
-
function exactKeys(raw, allowed, path) {
|
|
131
|
-
const keys = new Set(allowed);
|
|
132
|
-
for (const key of Object.keys(raw)) {
|
|
133
|
-
if (!keys.has(key)) malformed(`${path}.${key}`);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
144
|
function stringField(raw, key, path) {
|
|
137
145
|
const value = raw[key];
|
|
138
146
|
if (typeof value !== "string") return malformed(`${path}.${key}`);
|
|
@@ -163,14 +171,12 @@ function parseOffer(value, path) {
|
|
|
163
171
|
const unit = stringField(raw, "unit", path);
|
|
164
172
|
const maxUsd = numberField(raw, "maxUsd", path);
|
|
165
173
|
if (model === "flat") {
|
|
166
|
-
|
|
167
|
-
if (unit !== "request" || "baseUsd" in raw || "perUnitUsd" in raw) {
|
|
174
|
+
if (unit !== "request") {
|
|
168
175
|
return malformed(path);
|
|
169
176
|
}
|
|
170
177
|
return { model, unit, maxUsd };
|
|
171
178
|
}
|
|
172
179
|
if (model === "linear") {
|
|
173
|
-
exactKeys(raw, ["model", "unit", "baseUsd", "perUnitUsd", "maxUsd"], path);
|
|
174
180
|
if (unit.length === 0) return malformed(`${path}.unit`);
|
|
175
181
|
return {
|
|
176
182
|
model,
|
|
@@ -184,7 +190,6 @@ function parseOffer(value, path) {
|
|
|
184
190
|
}
|
|
185
191
|
function parsePricing(value, path) {
|
|
186
192
|
const raw = record(value, path);
|
|
187
|
-
exactKeys(raw, ["from", "failoverMaxUsd"], path);
|
|
188
193
|
return {
|
|
189
194
|
from: parseOffer(raw["from"], `${path}.from`),
|
|
190
195
|
failoverMaxUsd: numberField(raw, "failoverMaxUsd", path)
|
|
@@ -192,10 +197,8 @@ function parsePricing(value, path) {
|
|
|
192
197
|
}
|
|
193
198
|
function parseHealth(value, path) {
|
|
194
199
|
const raw = record(value, path);
|
|
195
|
-
exactKeys(raw, ["window", "uptimePct", "latencyP50Ms", "requests"], path);
|
|
196
|
-
if (raw["window"] !== "30d") return malformed(`${path}.window`);
|
|
197
200
|
return {
|
|
198
|
-
window: "
|
|
201
|
+
window: stringField(raw, "window", path),
|
|
199
202
|
uptimePct: boundedNumberField(raw, "uptimePct", path, void 0, 100),
|
|
200
203
|
latencyP50Ms: integerField(raw, "latencyP50Ms", path),
|
|
201
204
|
requests: integerField(raw, "requests", path)
|
|
@@ -203,7 +206,6 @@ function parseHealth(value, path) {
|
|
|
203
206
|
}
|
|
204
207
|
function parseLane(value, path) {
|
|
205
208
|
const raw = record(value, path);
|
|
206
|
-
exactKeys(raw, ["pricing", "health"], path);
|
|
207
209
|
const lane = {
|
|
208
210
|
pricing: parseOffer(raw["pricing"], `${path}.pricing`)
|
|
209
211
|
};
|
|
@@ -221,7 +223,6 @@ function parseSchema(value, path) {
|
|
|
221
223
|
}
|
|
222
224
|
function parseHighlight(value, path) {
|
|
223
225
|
const raw = record(value, path);
|
|
224
|
-
exactKeys(raw, ["path", "type", "why"], path);
|
|
225
226
|
const field = {
|
|
226
227
|
path: stringField(raw, "path", path),
|
|
227
228
|
type: stringField(raw, "type", path)
|
|
@@ -242,28 +243,10 @@ function mapProfile(raw) {
|
|
|
242
243
|
return profile;
|
|
243
244
|
}
|
|
244
245
|
function mapCatalogEntry(raw) {
|
|
245
|
-
|
|
246
|
+
rejectUnsafeDiscoveryFields(raw, "api");
|
|
246
247
|
const value = record(raw, "api");
|
|
247
|
-
exactKeys(
|
|
248
|
-
value,
|
|
249
|
-
[
|
|
250
|
-
"id",
|
|
251
|
-
"slug",
|
|
252
|
-
"category",
|
|
253
|
-
"name",
|
|
254
|
-
"description",
|
|
255
|
-
"provider",
|
|
256
|
-
"pricing",
|
|
257
|
-
"lanes",
|
|
258
|
-
"heavy",
|
|
259
|
-
"tryEligible",
|
|
260
|
-
"inputSchema",
|
|
261
|
-
"outputSchema"
|
|
262
|
-
],
|
|
263
|
-
"api"
|
|
264
|
-
);
|
|
265
248
|
const lanesRaw = value["lanes"];
|
|
266
|
-
if (!Array.isArray(lanesRaw)
|
|
249
|
+
if (!Array.isArray(lanesRaw)) {
|
|
267
250
|
return malformed("api.lanes");
|
|
268
251
|
}
|
|
269
252
|
const entry = {
|
|
@@ -285,32 +268,24 @@ function mapCatalogEntry(raw) {
|
|
|
285
268
|
}
|
|
286
269
|
if (typeof value["tryEligible"] !== "boolean")
|
|
287
270
|
return malformed("api.tryEligible");
|
|
271
|
+
if (value["failover"] !== void 0) {
|
|
272
|
+
if (typeof value["failover"] !== "boolean")
|
|
273
|
+
return malformed("api.failover");
|
|
274
|
+
entry.failover = value["failover"];
|
|
275
|
+
}
|
|
276
|
+
if (value["excludesCallerDelay"] !== void 0) {
|
|
277
|
+
if (typeof value["excludesCallerDelay"] !== "boolean")
|
|
278
|
+
return malformed("api.excludesCallerDelay");
|
|
279
|
+
entry.excludesCallerDelay = value["excludesCallerDelay"];
|
|
280
|
+
}
|
|
288
281
|
if (value["inputSchema"] !== void 0) {
|
|
289
282
|
entry.inputSchema = parseSchema(value["inputSchema"], "api.inputSchema");
|
|
290
283
|
}
|
|
291
284
|
if (value["outputSchema"] !== void 0) {
|
|
292
285
|
entry.outputSchema = parseSchema(value["outputSchema"], "api.outputSchema");
|
|
293
286
|
}
|
|
294
|
-
if (!offersEqual(entry.pricing.from, entry.lanes[0].pricing)) {
|
|
295
|
-
return malformed("api.pricing.from");
|
|
296
|
-
}
|
|
297
|
-
const failoverMaxUsd = Math.max(
|
|
298
|
-
...entry.lanes.map((lane) => lane.pricing.maxUsd)
|
|
299
|
-
);
|
|
300
|
-
if (entry.pricing.failoverMaxUsd !== failoverMaxUsd) {
|
|
301
|
-
return malformed("api.pricing.failoverMaxUsd");
|
|
302
|
-
}
|
|
303
287
|
return entry;
|
|
304
288
|
}
|
|
305
|
-
function offersEqual(left, right) {
|
|
306
|
-
if (left.model !== right.model || left.unit !== right.unit || left.maxUsd !== right.maxUsd) {
|
|
307
|
-
return false;
|
|
308
|
-
}
|
|
309
|
-
if (left.model === "flat" || right.model === "flat") {
|
|
310
|
-
return left.model === right.model;
|
|
311
|
-
}
|
|
312
|
-
return left.baseUsd === right.baseUsd && left.perUnitUsd === right.perUnitUsd;
|
|
313
|
-
}
|
|
314
289
|
function mapCatalogDetail(raw) {
|
|
315
290
|
const entry = mapCatalogEntry(raw);
|
|
316
291
|
if (entry.inputSchema === void 0) return malformed("api.inputSchema");
|
|
@@ -318,28 +293,13 @@ function mapCatalogDetail(raw) {
|
|
|
318
293
|
return entry;
|
|
319
294
|
}
|
|
320
295
|
function mapCatalogList(raw) {
|
|
296
|
+
rejectUnsafeDiscoveryFields(raw, "catalog");
|
|
321
297
|
const envelope = record(raw, "catalog");
|
|
322
|
-
exactKeys(envelope, ["apis"], "catalog");
|
|
323
298
|
if (!Array.isArray(envelope["apis"])) return malformed("catalog.apis");
|
|
324
299
|
return envelope["apis"].map(mapCatalogEntry);
|
|
325
300
|
}
|
|
326
301
|
function mapSearchResult(value, path) {
|
|
327
302
|
const raw = record(value, path);
|
|
328
|
-
exactKeys(
|
|
329
|
-
raw,
|
|
330
|
-
[
|
|
331
|
-
"slug",
|
|
332
|
-
"platformId",
|
|
333
|
-
"name",
|
|
334
|
-
"description",
|
|
335
|
-
"category",
|
|
336
|
-
"provider",
|
|
337
|
-
"pricing",
|
|
338
|
-
"relevance",
|
|
339
|
-
"highlightFields"
|
|
340
|
-
],
|
|
341
|
-
path
|
|
342
|
-
);
|
|
343
303
|
const result = {
|
|
344
304
|
slug: stringField(raw, "slug", path),
|
|
345
305
|
platformId: stringField(raw, "platformId", path),
|
|
@@ -360,9 +320,8 @@ function mapSearchResult(value, path) {
|
|
|
360
320
|
return result;
|
|
361
321
|
}
|
|
362
322
|
function mapCatalogSearch(raw) {
|
|
363
|
-
|
|
323
|
+
rejectUnsafeDiscoveryFields(raw, "search");
|
|
364
324
|
const envelope = record(raw, "search");
|
|
365
|
-
exactKeys(envelope, ["results", "total", "ranking"], "search");
|
|
366
325
|
if (!Array.isArray(envelope["results"])) return malformed("search.results");
|
|
367
326
|
const ranking = envelope["ranking"];
|
|
368
327
|
if (ranking !== "semantic" && ranking !== "keyword")
|
|
@@ -407,7 +366,7 @@ async function agentSignup(options = {}) {
|
|
|
407
366
|
0
|
|
408
367
|
);
|
|
409
368
|
}
|
|
410
|
-
const requestId = response.headers
|
|
369
|
+
const requestId = requestIdOf(response.headers);
|
|
411
370
|
const text = await response.text().catch(() => "");
|
|
412
371
|
if (response.status !== 200) {
|
|
413
372
|
let message = `request failed with status ${response.status}`;
|
|
@@ -439,6 +398,8 @@ var DEFAULT_TIMEOUT_MS = 6e4;
|
|
|
439
398
|
var DEFAULT_MAX_RETRIES = 2;
|
|
440
399
|
var RETRY_BASE_DELAY_MS = 500;
|
|
441
400
|
var RETRY_MAX_DELAY_MS = 8e3;
|
|
401
|
+
var DEFAULT_MAX_IN_PROGRESS_WAIT_MS = 6e4;
|
|
402
|
+
var IDEMPOTENCY_IN_PROGRESS_CODE = "idempotency_in_progress";
|
|
442
403
|
var PRE_SEND_NETWORK_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
443
404
|
"EADDRNOTAVAIL",
|
|
444
405
|
"EAI_AGAIN",
|
|
@@ -482,7 +443,7 @@ function backoffDelay(attempt) {
|
|
|
482
443
|
const factor = 0.5 + Math.random();
|
|
483
444
|
return base * factor;
|
|
484
445
|
}
|
|
485
|
-
function
|
|
446
|
+
function parseRetryAfterMs(header) {
|
|
486
447
|
if (header === null) {
|
|
487
448
|
return void 0;
|
|
488
449
|
}
|
|
@@ -492,13 +453,11 @@ function parseRetryAfter(header) {
|
|
|
492
453
|
}
|
|
493
454
|
const seconds = Number(trimmed);
|
|
494
455
|
if (Number.isFinite(seconds)) {
|
|
495
|
-
|
|
496
|
-
return Math.min(Math.max(ms, 0), RETRY_MAX_DELAY_MS);
|
|
456
|
+
return Math.max(seconds * 1e3, 0);
|
|
497
457
|
}
|
|
498
458
|
const dateMs = Date.parse(trimmed);
|
|
499
459
|
if (Number.isFinite(dateMs)) {
|
|
500
|
-
|
|
501
|
-
return Math.min(Math.max(delta, 0), RETRY_MAX_DELAY_MS);
|
|
460
|
+
return Math.max(dateMs - Date.now(), 0);
|
|
502
461
|
}
|
|
503
462
|
return void 0;
|
|
504
463
|
}
|
|
@@ -603,6 +562,7 @@ var AnyAPI = class {
|
|
|
603
562
|
maxRetries;
|
|
604
563
|
timeoutMs;
|
|
605
564
|
idempotency;
|
|
565
|
+
maxInProgressWaitMs;
|
|
606
566
|
/**
|
|
607
567
|
* The network seam the generated per-platform namespaces target. The base client IS a
|
|
608
568
|
* ClientCore (it implements `run`), so the generated subclass hands `this._core` to each
|
|
@@ -625,6 +585,7 @@ var AnyAPI = class {
|
|
|
625
585
|
this.fetchImpl = resolvedFetch;
|
|
626
586
|
this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
627
587
|
this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
588
|
+
this.maxInProgressWaitMs = options.maxInProgressWaitMs ?? DEFAULT_MAX_IN_PROGRESS_WAIT_MS;
|
|
628
589
|
const idempotency = options.idempotency ?? "auto";
|
|
629
590
|
if (idempotency !== "auto" && idempotency !== "off") {
|
|
630
591
|
throw new TypeError('idempotency must be "auto" or "off"');
|
|
@@ -645,6 +606,7 @@ var AnyAPI = class {
|
|
|
645
606
|
body,
|
|
646
607
|
timeoutMs: options?.timeoutMs ?? this.timeoutMs,
|
|
647
608
|
maxRetries: options?.maxRetries ?? this.maxRetries,
|
|
609
|
+
maxInProgressWaitMs: options?.maxInProgressWaitMs ?? this.maxInProgressWaitMs,
|
|
648
610
|
...options?.idempotencyKey !== void 0 ? { idempotencyKey: options.idempotencyKey } : {},
|
|
649
611
|
...options?.signal ? { signal: options.signal } : {}
|
|
650
612
|
}
|
|
@@ -717,6 +679,11 @@ var AnyAPI = class {
|
|
|
717
679
|
headers["Idempotency-Key"] = key;
|
|
718
680
|
}
|
|
719
681
|
let attempt = 0;
|
|
682
|
+
let inProgressWaitedMs = 0;
|
|
683
|
+
const inProgressBudgetMs = Math.max(
|
|
684
|
+
opts.maxInProgressWaitMs ?? DEFAULT_MAX_IN_PROGRESS_WAIT_MS,
|
|
685
|
+
0
|
|
686
|
+
);
|
|
720
687
|
for (; ; ) {
|
|
721
688
|
const { signal, timeoutSignal } = composeSignal(
|
|
722
689
|
opts.timeoutMs,
|
|
@@ -750,7 +717,7 @@ var AnyAPI = class {
|
|
|
750
717
|
}
|
|
751
718
|
throw connErr;
|
|
752
719
|
}
|
|
753
|
-
const requestId = response.headers
|
|
720
|
+
const requestId = requestIdOf(response.headers);
|
|
754
721
|
if (response.status === 200) {
|
|
755
722
|
const text = await response.text();
|
|
756
723
|
try {
|
|
@@ -765,13 +732,22 @@ var AnyAPI = class {
|
|
|
765
732
|
}
|
|
766
733
|
const body = await response.text().catch(() => "");
|
|
767
734
|
const { message, code } = messageFromBody(body, response.status);
|
|
735
|
+
const retryAfterMs = parseRetryAfterMs(response.headers.get("retry-after"));
|
|
768
736
|
if (response.status === 429 && attempt < opts.maxRetries) {
|
|
769
|
-
const
|
|
770
|
-
const delay = retryAfter ?? backoffDelay(attempt);
|
|
737
|
+
const delay = retryAfterMs !== void 0 ? Math.min(retryAfterMs, RETRY_MAX_DELAY_MS) : backoffDelay(attempt);
|
|
771
738
|
await sleep(delay, opts.signal);
|
|
772
739
|
attempt += 1;
|
|
773
740
|
continue;
|
|
774
741
|
}
|
|
742
|
+
if (billedPost && response.status === 409 && code === IDEMPOTENCY_IN_PROGRESS_CODE && attempt < opts.maxRetries) {
|
|
743
|
+
const delay = retryAfterMs ?? backoffDelay(attempt);
|
|
744
|
+
if (inProgressWaitedMs + delay <= inProgressBudgetMs) {
|
|
745
|
+
await sleep(delay, opts.signal);
|
|
746
|
+
inProgressWaitedMs += delay;
|
|
747
|
+
attempt += 1;
|
|
748
|
+
continue;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
775
751
|
throw errorFromStatus(response.status, message, requestId, code);
|
|
776
752
|
}
|
|
777
753
|
}
|