@apifuse/provider-sdk 2.2.0-beta.3 → 2.2.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AUTHORING.md +14 -0
- package/CHANGELOG.md +4 -0
- package/bin/apifuse-check.ts +18 -58
- package/bin/apifuse-create.ts +1 -1
- package/bin/apifuse-dev.ts +27 -52
- package/bin/apifuse-pack-smoke.ts +22 -81
- package/bin/apifuse-pack-types.ts +266 -0
- package/bin/apifuse-perf.ts +45 -127
- package/bin/apifuse-record.ts +23 -61
- package/bin/apifuse-submit-check.ts +26 -21
- package/bin/apifuse.ts +1 -1
- package/bin/submit-check-xml.ts +1 -1
- package/dist/auth-turn/index.d.ts +1 -1
- package/dist/auth.d.ts +2 -2
- package/dist/auth.js +9 -18
- package/dist/ceremonies/index.d.ts +1 -1
- package/dist/ceremonies/index.js +8 -18
- package/dist/config/loader.d.ts +2 -2
- package/dist/config/loader.js +19 -42
- package/dist/contract-serialization.d.ts +2 -2
- package/dist/contract-serialization.js +3 -6
- package/dist/contract-types.d.ts +2 -2
- package/dist/contract.d.ts +3 -3
- package/dist/contract.js +4 -6
- package/dist/define.d.ts +8 -1
- package/dist/define.js +57 -115
- package/dist/dev.d.ts +1 -1
- package/dist/dev.js +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +1 -3
- package/dist/i18n/catalog.d.ts +2 -2
- package/dist/i18n/catalog.js +4 -10
- package/dist/i18n/index.d.ts +2 -2
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/keys.d.ts +2 -2
- package/dist/index.d.ts +43 -42
- package/dist/index.js +38 -37
- package/dist/lint.js +8 -15
- package/dist/provider.d.ts +11 -11
- package/dist/provider.js +9 -9
- package/dist/public-schema-field-lint.d.ts +1 -1
- package/dist/recipes/gov-api.js +1 -1
- package/dist/runtime/auth-flow.d.ts +1 -1
- package/dist/runtime/auth-flow.js +3 -3
- package/dist/runtime/browser.d.ts +1 -1
- package/dist/runtime/browser.js +15 -29
- package/dist/runtime/cache.d.ts +1 -1
- package/dist/runtime/cache.js +4 -8
- package/dist/runtime/choice.d.ts +1 -1
- package/dist/runtime/choice.js +12 -34
- package/dist/runtime/credential.d.ts +1 -1
- package/dist/runtime/credential.js +1 -1
- package/dist/runtime/env.d.ts +1 -1
- package/dist/runtime/executor.d.ts +1 -1
- package/dist/runtime/executor.js +2 -2
- package/dist/runtime/http.d.ts +2 -2
- package/dist/runtime/http.js +5 -5
- package/dist/runtime/insights.d.ts +1 -1
- package/dist/runtime/insights.js +6 -13
- package/dist/runtime/instrumentation.d.ts +2 -2
- package/dist/runtime/instrumentation.js +5 -15
- package/dist/runtime/keyring.js +1 -1
- package/dist/runtime/namespace.js +1 -1
- package/dist/runtime/otlp.d.ts +1 -1
- package/dist/runtime/perf.d.ts +1 -1
- package/dist/runtime/provider.d.ts +1 -1
- package/dist/runtime/provider.js +1 -2
- package/dist/runtime/proxy-errors.d.ts +1 -1
- package/dist/runtime/proxy-errors.js +3 -5
- package/dist/runtime/proxy-retry-policy.d.ts +2 -2
- package/dist/runtime/proxy-retry-policy.js +2 -2
- package/dist/runtime/proxy-telemetry.d.ts +1 -1
- package/dist/runtime/proxy-telemetry.js +16 -48
- package/dist/runtime/redis.d.ts +1 -1
- package/dist/runtime/redis.js +2 -4
- package/dist/runtime/request-options.d.ts +1 -1
- package/dist/runtime/state.d.ts +2 -2
- package/dist/runtime/state.js +3 -3
- package/dist/runtime/stealth.d.ts +2 -2
- package/dist/runtime/stealth.js +6 -6
- package/dist/runtime/stt.d.ts +1 -1
- package/dist/runtime/stt.js +11 -15
- package/dist/runtime/trace.d.ts +2 -2
- package/dist/runtime/trace.js +2 -4
- package/dist/runtime/waterfall.d.ts +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +7 -15
- package/dist/serve.d.ts +1 -1
- package/dist/serve.js +1 -1
- package/dist/server/index.d.ts +7 -7
- package/dist/server/index.js +6 -6
- package/dist/server/self-test-redaction.d.ts +1 -1
- package/dist/server/self-test-redaction.js +1 -1
- package/dist/server/self-test.d.ts +3 -3
- package/dist/server/self-test.js +3 -3
- package/dist/server/serve.d.ts +3 -3
- package/dist/server/serve.js +36 -49
- package/dist/server/types.js +2 -7
- package/dist/stealth/profiles.d.ts +1 -1
- package/dist/stealth/profiles.js +5 -14
- package/dist/stream.d.ts +1 -1
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +2 -2
- package/dist/testing/run.d.ts +1 -1
- package/dist/testing/run.js +7 -14
- package/dist/types.d.ts +57 -0
- package/dist/user-input.d.ts +30 -0
- package/dist/user-input.js +66 -0
- package/package.json +6 -4
- package/src/auth-turn/index.ts +1 -1
- package/src/auth.ts +28 -86
- package/src/ceremonies/index.ts +24 -78
- package/src/config/loader.ts +58 -176
- package/src/contract-serialization.ts +5 -11
- package/src/contract-types.ts +2 -2
- package/src/contract.ts +12 -28
- package/src/define.ts +174 -495
- package/src/dev.ts +4 -9
- package/src/errors.ts +4 -11
- package/src/i18n/catalog.ts +10 -32
- package/src/i18n/index.ts +2 -2
- package/src/i18n/keys.ts +5 -11
- package/src/index.ts +44 -42
- package/src/lint.ts +89 -159
- package/src/provider.ts +12 -11
- package/src/public-schema-field-lint.ts +7 -33
- package/src/recipes/gov-api.ts +2 -5
- package/src/runtime/auth-flow.ts +5 -7
- package/src/runtime/browser.ts +64 -187
- package/src/runtime/cache.ts +20 -67
- package/src/runtime/choice.ts +55 -129
- package/src/runtime/credential.ts +2 -2
- package/src/runtime/env.ts +1 -1
- package/src/runtime/executor.ts +9 -19
- package/src/runtime/http.ts +7 -7
- package/src/runtime/insights.ts +15 -53
- package/src/runtime/instrumentation.ts +19 -58
- package/src/runtime/keyring.ts +7 -19
- package/src/runtime/namespace.ts +2 -7
- package/src/runtime/otlp.ts +12 -23
- package/src/runtime/perf.ts +1 -1
- package/src/runtime/provider.ts +4 -9
- package/src/runtime/proxy-errors.ts +17 -38
- package/src/runtime/proxy-retry-policy.ts +3 -3
- package/src/runtime/proxy-telemetry.ts +23 -72
- package/src/runtime/redis.ts +4 -12
- package/src/runtime/request-options.ts +4 -13
- package/src/runtime/state.ts +30 -109
- package/src/runtime/stealth.ts +8 -8
- package/src/runtime/stt.ts +38 -94
- package/src/runtime/trace.ts +14 -44
- package/src/runtime/waterfall.ts +5 -18
- package/src/schema.ts +23 -84
- package/src/serve.ts +1 -1
- package/src/server/index.ts +7 -7
- package/src/server/self-test-redaction.ts +2 -2
- package/src/server/self-test.ts +5 -5
- package/src/server/serve.ts +87 -242
- package/src/server/types.ts +6 -19
- package/src/stealth/profiles.ts +10 -26
- package/src/stream.ts +8 -19
- package/src/testing/index.ts +2 -2
- package/src/testing/run.ts +19 -67
- package/src/types.ts +58 -0
- package/src/user-input.ts +118 -0
package/src/config/loader.ts
CHANGED
|
@@ -2,9 +2,9 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
|
|
5
|
-
import Redis from "ioredis";
|
|
5
|
+
import { Redis } from "ioredis";
|
|
6
6
|
|
|
7
|
-
import type { ProviderProxyPolicy, TraceConfig } from "../types";
|
|
7
|
+
import type { ProviderProxyPolicy, TraceConfig } from "../types.js";
|
|
8
8
|
|
|
9
9
|
export const SMARTPROXY_APP_KEY_ENV = "APIFUSE__PROXY__SMARTPROXY_APP_KEY";
|
|
10
10
|
export const SMARTPROXY_MAX_LIFETIME_MINUTES = 2000;
|
|
@@ -12,12 +12,9 @@ export const DEFAULT_SMARTPROXY_POOL_SIZE = 20;
|
|
|
12
12
|
export const SMARTPROXY_MAX_POOL_SIZE = 20;
|
|
13
13
|
export const DEFAULT_PROXY_PROVIDER_ENV = "APIFUSE__PROXY__PROVIDER";
|
|
14
14
|
export const DEFAULT_PROXY_COUNTRY_ENV = "APIFUSE__PROXY__DEFAULT_COUNTRY";
|
|
15
|
-
export const DEFAULT_PROXY_LIFETIME_ENV =
|
|
16
|
-
|
|
17
|
-
export const
|
|
18
|
-
"APIFUSE__PROVIDER__CACHE_REDIS_URL";
|
|
19
|
-
export const PROVIDER_STATE_REDIS_URL_ENV =
|
|
20
|
-
"APIFUSE__PROVIDER__STATE_REDIS_URL";
|
|
15
|
+
export const DEFAULT_PROXY_LIFETIME_ENV = "APIFUSE__PROXY__DEFAULT_LIFETIME_MINUTES";
|
|
16
|
+
export const PROVIDER_CACHE_REDIS_URL_ENV = "APIFUSE__PROVIDER__CACHE_REDIS_URL";
|
|
17
|
+
export const PROVIDER_STATE_REDIS_URL_ENV = "APIFUSE__PROVIDER__STATE_REDIS_URL";
|
|
21
18
|
export const REDIS_URL_ENV = "APIFUSE__REDIS__URL";
|
|
22
19
|
|
|
23
20
|
export type ProxyOptions = {
|
|
@@ -165,8 +162,7 @@ const SMARTPROXY_LOCK_POLL_MAX_MS = 9_000;
|
|
|
165
162
|
const SMARTPROXY_DEADLINE_MARGIN_MS = 1_000;
|
|
166
163
|
const SMARTPROXY_INVALIDATION_SKIP_REDIS_MS = 30_000;
|
|
167
164
|
const SMARTPROXY_ALLOCATOR_MAX_ATTEMPTS = 3;
|
|
168
|
-
const SMARTPROXY_ALLOCATOR_DEADLINE_MS =
|
|
169
|
-
SMARTPROXY_LOCK_TTL_MS - SMARTPROXY_DEADLINE_MARGIN_MS;
|
|
165
|
+
const SMARTPROXY_ALLOCATOR_DEADLINE_MS = SMARTPROXY_LOCK_TTL_MS - SMARTPROXY_DEADLINE_MARGIN_MS;
|
|
170
166
|
const SMARTPROXY_ALLOCATOR_RETRY_BASE_MS = 25;
|
|
171
167
|
// Smartproxy API extraction returns fresh IP:port candidates; the `life`
|
|
172
168
|
// parameter controls session duration intent, not a hard endpoint lease. Keep
|
|
@@ -197,15 +193,11 @@ export function providerStateRedisUrlFromEnv(): string | undefined {
|
|
|
197
193
|
}
|
|
198
194
|
|
|
199
195
|
/** @internal Test-only hook for exercising shared proxy-cache behavior. */
|
|
200
|
-
export function __setProxyRedisForTests(
|
|
201
|
-
redis: ProxyRedisClient | undefined,
|
|
202
|
-
): void {
|
|
196
|
+
export function __setProxyRedisForTests(redis: ProxyRedisClient | undefined): void {
|
|
203
197
|
proxyRedisForTests = redis;
|
|
204
198
|
}
|
|
205
199
|
|
|
206
|
-
export function __setSmartproxyAllocatorDeadlineMsForTests(
|
|
207
|
-
deadlineMs: number | undefined,
|
|
208
|
-
): void {
|
|
200
|
+
export function __setSmartproxyAllocatorDeadlineMsForTests(deadlineMs: number | undefined): void {
|
|
209
201
|
smartproxyAllocatorDeadlineMsForTests = deadlineMs;
|
|
210
202
|
}
|
|
211
203
|
|
|
@@ -230,9 +222,7 @@ function getProxyRedis(): ProxyRedisClient | undefined {
|
|
|
230
222
|
return redis;
|
|
231
223
|
}
|
|
232
224
|
|
|
233
|
-
async function withRedisTimeout<T>(
|
|
234
|
-
operation: () => Promise<T>,
|
|
235
|
-
): Promise<T | undefined> {
|
|
225
|
+
async function withRedisTimeout<T>(operation: () => Promise<T>): Promise<T | undefined> {
|
|
236
226
|
let timeoutId: ReturnType<typeof setTimeout> | undefined;
|
|
237
227
|
try {
|
|
238
228
|
const timeout = new Promise<undefined>((resolve) => {
|
|
@@ -318,17 +308,11 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
|
|
318
308
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
319
309
|
}
|
|
320
310
|
|
|
321
|
-
function toProxyDiagnostics(
|
|
322
|
-
value: unknown,
|
|
323
|
-
): Record<string, string | number | boolean> | undefined {
|
|
311
|
+
function toProxyDiagnostics(value: unknown): Record<string, string | number | boolean> | undefined {
|
|
324
312
|
if (!isRecord(value)) return undefined;
|
|
325
313
|
const diagnostics: Record<string, string | number | boolean> = {};
|
|
326
314
|
for (const [key, item] of Object.entries(value)) {
|
|
327
|
-
if (
|
|
328
|
-
typeof item === "string" ||
|
|
329
|
-
typeof item === "number" ||
|
|
330
|
-
typeof item === "boolean"
|
|
331
|
-
) {
|
|
315
|
+
if (typeof item === "string" || typeof item === "number" || typeof item === "boolean") {
|
|
332
316
|
diagnostics[key] = item;
|
|
333
317
|
}
|
|
334
318
|
}
|
|
@@ -411,11 +395,8 @@ function applyStickyProxySession(proxyUrl: string): string {
|
|
|
411
395
|
}
|
|
412
396
|
|
|
413
397
|
const username = decodeURIComponent(parsed.username);
|
|
414
|
-
const sessionId =
|
|
415
|
-
|
|
416
|
-
const sessionDuration = readPositiveIntegerEnv(
|
|
417
|
-
"APIFUSE__PROXY__SESSION_DURATION",
|
|
418
|
-
);
|
|
398
|
+
const sessionId = process.env.APIFUSE__PROXY__SESSION_ID?.trim() || "apifuse-shared";
|
|
399
|
+
const sessionDuration = readPositiveIntegerEnv("APIFUSE__PROXY__SESSION_DURATION");
|
|
419
400
|
const stickyUsername = host.includes("smartproxy")
|
|
420
401
|
? buildSmartproxyUsername(username, sessionId, sessionDuration)
|
|
421
402
|
: buildDecodoUsername(username, sessionId, sessionDuration ?? "60");
|
|
@@ -430,27 +411,16 @@ function buildSmartproxyUsername(
|
|
|
430
411
|
sessionDuration?: string,
|
|
431
412
|
): string {
|
|
432
413
|
const parts = username.split("_");
|
|
433
|
-
const configuredLife = parts
|
|
434
|
-
.find((part) => part.startsWith("life-"))
|
|
435
|
-
?.slice("life-".length);
|
|
414
|
+
const configuredLife = parts.find((part) => part.startsWith("life-"))?.slice("life-".length);
|
|
436
415
|
const baseUsername = parts
|
|
437
416
|
.filter((part) => !part.startsWith("session-") && !part.startsWith("life-"))
|
|
438
417
|
.join("_");
|
|
439
418
|
return `${baseUsername}_session-${sessionId}_life-${sessionDuration ?? configuredLife ?? "60"}`;
|
|
440
419
|
}
|
|
441
420
|
|
|
442
|
-
function buildDecodoUsername(
|
|
443
|
-
username
|
|
444
|
-
|
|
445
|
-
sessionDuration: string,
|
|
446
|
-
): string {
|
|
447
|
-
const withoutSticky = username.replace(
|
|
448
|
-
/-session-.+-sessionduration-\d+$/,
|
|
449
|
-
"",
|
|
450
|
-
);
|
|
451
|
-
const baseUsername = withoutSticky.startsWith("user-")
|
|
452
|
-
? withoutSticky
|
|
453
|
-
: `user-${withoutSticky}`;
|
|
421
|
+
function buildDecodoUsername(username: string, sessionId: string, sessionDuration: string): string {
|
|
422
|
+
const withoutSticky = username.replace(/-session-.+-sessionduration-\d+$/, "");
|
|
423
|
+
const baseUsername = withoutSticky.startsWith("user-") ? withoutSticky : `user-${withoutSticky}`;
|
|
454
424
|
return `${baseUsername}-session-${sessionId}-sessionduration-${sessionDuration}`;
|
|
455
425
|
}
|
|
456
426
|
|
|
@@ -461,9 +431,7 @@ function syncProxyEnv(config: ApiFuseConfig): void {
|
|
|
461
431
|
}
|
|
462
432
|
}
|
|
463
433
|
|
|
464
|
-
export function resolveProxyConfig(
|
|
465
|
-
options: ProxyResolutionOptions = {},
|
|
466
|
-
): ResolvedProxyConfig {
|
|
434
|
+
export function resolveProxyConfig(options: ProxyResolutionOptions = {}): ResolvedProxyConfig {
|
|
467
435
|
const explicitProxyUrl = normalizeProxyUrl(options.proxy);
|
|
468
436
|
if (explicitProxyUrl) {
|
|
469
437
|
return { shouldWarn: false, url: explicitProxyUrl };
|
|
@@ -485,9 +453,7 @@ export function resolveProxyConfig(
|
|
|
485
453
|
return { shouldWarn: false, url: envProxyUrl };
|
|
486
454
|
}
|
|
487
455
|
|
|
488
|
-
const configuredProxyUrl = normalizeProxyUrl(
|
|
489
|
-
options.apifuseConfig?.proxy?.url,
|
|
490
|
-
);
|
|
456
|
+
const configuredProxyUrl = normalizeProxyUrl(options.apifuseConfig?.proxy?.url);
|
|
491
457
|
if (configuredProxyUrl) {
|
|
492
458
|
return { shouldWarn: false, url: configuredProxyUrl };
|
|
493
459
|
}
|
|
@@ -539,10 +505,7 @@ export async function resolveProxyConfigAsync(
|
|
|
539
505
|
options.affinityKey,
|
|
540
506
|
);
|
|
541
507
|
options.telemetry?.recordProxyResolution(allocated.telemetry);
|
|
542
|
-
const poolIndex = selectProxyPoolIndex(
|
|
543
|
-
allocated.pool.urls.length,
|
|
544
|
-
options.proxyAttempt,
|
|
545
|
-
);
|
|
508
|
+
const poolIndex = selectProxyPoolIndex(allocated.pool.urls.length, options.proxyAttempt);
|
|
546
509
|
return {
|
|
547
510
|
shouldWarn: false,
|
|
548
511
|
url: allocated.pool.urls[poolIndex],
|
|
@@ -570,9 +533,7 @@ export async function resolveProxyConfigAsync(
|
|
|
570
533
|
}
|
|
571
534
|
}
|
|
572
535
|
|
|
573
|
-
function resolvePolicy(
|
|
574
|
-
options: ProxyResolutionOptions,
|
|
575
|
-
): ProviderProxyPolicy | undefined {
|
|
536
|
+
function resolvePolicy(options: ProxyResolutionOptions): ProviderProxyPolicy | undefined {
|
|
576
537
|
if (options.proxyPolicy) {
|
|
577
538
|
return options.proxyPolicy;
|
|
578
539
|
}
|
|
@@ -585,30 +546,20 @@ function resolvePolicy(
|
|
|
585
546
|
|
|
586
547
|
function resolveProxyProvider(policy: ProviderProxyPolicy): string {
|
|
587
548
|
return (
|
|
588
|
-
policy.provider ??
|
|
589
|
-
process.env[DEFAULT_PROXY_PROVIDER_ENV]?.trim().toLowerCase() ??
|
|
590
|
-
"custom"
|
|
549
|
+
policy.provider ?? process.env[DEFAULT_PROXY_PROVIDER_ENV]?.trim().toLowerCase() ?? "custom"
|
|
591
550
|
);
|
|
592
551
|
}
|
|
593
552
|
|
|
594
|
-
function resolveSmartproxyCountry(
|
|
595
|
-
policy: ProviderProxyPolicy,
|
|
596
|
-
): string | undefined {
|
|
553
|
+
function resolveSmartproxyCountry(policy: ProviderProxyPolicy): string | undefined {
|
|
597
554
|
return (
|
|
598
|
-
policy.geo?.country ??
|
|
599
|
-
process.env[DEFAULT_PROXY_COUNTRY_ENV]?.trim().toUpperCase() ??
|
|
600
|
-
undefined
|
|
555
|
+
policy.geo?.country ?? process.env[DEFAULT_PROXY_COUNTRY_ENV]?.trim().toUpperCase() ?? undefined
|
|
601
556
|
);
|
|
602
557
|
}
|
|
603
558
|
|
|
604
559
|
function resolveSmartproxyLifetime(policy: ProviderProxyPolicy): number {
|
|
605
560
|
const configuredLifetime =
|
|
606
|
-
policy.session?.lifetimeMinutes ??
|
|
607
|
-
|
|
608
|
-
return Math.min(
|
|
609
|
-
SMARTPROXY_MAX_LIFETIME_MINUTES,
|
|
610
|
-
Math.max(1, Math.floor(configuredLifetime)),
|
|
611
|
-
);
|
|
561
|
+
policy.session?.lifetimeMinutes ?? readPositiveNumberEnv(DEFAULT_PROXY_LIFETIME_ENV, 30);
|
|
562
|
+
return Math.min(SMARTPROXY_MAX_LIFETIME_MINUTES, Math.max(1, Math.floor(configuredLifetime)));
|
|
612
563
|
}
|
|
613
564
|
|
|
614
565
|
function readPositiveNumberEnv(name: string, fallback: number): number {
|
|
@@ -624,10 +575,7 @@ function readPositiveNumberEnv(name: string, fallback: number): number {
|
|
|
624
575
|
function resolveSmartproxyPoolSize(policy: ProviderProxyPolicy): number {
|
|
625
576
|
return Math.min(
|
|
626
577
|
SMARTPROXY_MAX_POOL_SIZE,
|
|
627
|
-
Math.max(
|
|
628
|
-
1,
|
|
629
|
-
Math.floor(policy.session?.poolSize ?? DEFAULT_SMARTPROXY_POOL_SIZE),
|
|
630
|
-
),
|
|
578
|
+
Math.max(1, Math.floor(policy.session?.poolSize ?? DEFAULT_SMARTPROXY_POOL_SIZE)),
|
|
631
579
|
);
|
|
632
580
|
}
|
|
633
581
|
|
|
@@ -635,9 +583,7 @@ function selectProxyPoolIndex(poolSize: number, attempt = 0): number {
|
|
|
635
583
|
if (poolSize <= 1) {
|
|
636
584
|
return 0;
|
|
637
585
|
}
|
|
638
|
-
const normalizedAttempt = Number.isFinite(attempt)
|
|
639
|
-
? Math.max(0, Math.floor(attempt))
|
|
640
|
-
: 0;
|
|
586
|
+
const normalizedAttempt = Number.isFinite(attempt) ? Math.max(0, Math.floor(attempt)) : 0;
|
|
641
587
|
return normalizedAttempt % poolSize;
|
|
642
588
|
}
|
|
643
589
|
|
|
@@ -651,10 +597,7 @@ function buildSmartproxyCacheKey(
|
|
|
651
597
|
provider: "smartproxy",
|
|
652
598
|
country: resolveSmartproxyCountry(policy),
|
|
653
599
|
affinity: policy.session?.affinity ?? "request",
|
|
654
|
-
affinityKey:
|
|
655
|
-
(policy.session?.affinity ?? "request") === "request"
|
|
656
|
-
? undefined
|
|
657
|
-
: affinityKey,
|
|
600
|
+
affinityKey: (policy.session?.affinity ?? "request") === "request" ? undefined : affinityKey,
|
|
658
601
|
lifetimeMinutes,
|
|
659
602
|
poolSize,
|
|
660
603
|
});
|
|
@@ -666,11 +609,7 @@ async function allocateSmartproxy(
|
|
|
666
609
|
lifetimeMinutes: number,
|
|
667
610
|
affinityKey: string | undefined,
|
|
668
611
|
): Promise<SmartproxyAllocationResult> {
|
|
669
|
-
const cacheKey = buildSmartproxyCacheKey(
|
|
670
|
-
policy,
|
|
671
|
-
affinityKey,
|
|
672
|
-
lifetimeMinutes,
|
|
673
|
-
);
|
|
612
|
+
const cacheKey = buildSmartproxyCacheKey(policy, affinityKey, lifetimeMinutes);
|
|
674
613
|
const startedAt = Date.now();
|
|
675
614
|
const now = startedAt;
|
|
676
615
|
const invalidatedUntil = invalidatedProxyKeys.get(cacheKey) ?? 0;
|
|
@@ -730,9 +669,7 @@ async function readSmartproxyRedisPool(
|
|
|
730
669
|
const redis = getProxyRedis();
|
|
731
670
|
if (!redis || !(await ensureRedisReady(redis))) return null;
|
|
732
671
|
const redisStartedAt = Date.now();
|
|
733
|
-
const raw = await withRedisTimeout(() =>
|
|
734
|
-
redis.get(smartproxyRedisPoolKey(cacheKey)),
|
|
735
|
-
);
|
|
672
|
+
const raw = await withRedisTimeout(() => redis.get(smartproxyRedisPoolKey(cacheKey)));
|
|
736
673
|
const redisReadMs = Math.max(0, Date.now() - redisStartedAt);
|
|
737
674
|
if (typeof raw !== "string") return null;
|
|
738
675
|
const pool = safeParseSmartproxyPool(raw);
|
|
@@ -756,16 +693,9 @@ async function refreshSmartproxyPool(
|
|
|
756
693
|
lifetimeMinutes: number,
|
|
757
694
|
): Promise<void> {
|
|
758
695
|
try {
|
|
759
|
-
await allocateSmartproxyShared(
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
appKey,
|
|
763
|
-
lifetimeMinutes,
|
|
764
|
-
Date.now(),
|
|
765
|
-
{
|
|
766
|
-
background: true,
|
|
767
|
-
},
|
|
768
|
-
);
|
|
696
|
+
await allocateSmartproxyShared(cacheKey, policy, appKey, lifetimeMinutes, Date.now(), {
|
|
697
|
+
background: true,
|
|
698
|
+
});
|
|
769
699
|
} catch {
|
|
770
700
|
// Soft refresh is opportunistic; current fresh pool remains usable.
|
|
771
701
|
}
|
|
@@ -809,9 +739,7 @@ async function allocateSmartproxyShared(
|
|
|
809
739
|
lifetimeMinutes,
|
|
810
740
|
startedAt,
|
|
811
741
|
{
|
|
812
|
-
cacheStatus: options.background
|
|
813
|
-
? "soft_stale_refresh"
|
|
814
|
-
: "allocator",
|
|
742
|
+
cacheStatus: options.background ? "soft_stale_refresh" : "allocator",
|
|
815
743
|
redis,
|
|
816
744
|
poolKey,
|
|
817
745
|
},
|
|
@@ -838,15 +766,10 @@ async function allocateSmartproxyShared(
|
|
|
838
766
|
if (typeof pttl === "number" && pttl <= 0) {
|
|
839
767
|
continue;
|
|
840
768
|
}
|
|
841
|
-
if (
|
|
842
|
-
Date.now() - startedAt >
|
|
843
|
-
SMARTPROXY_LOCK_POLL_MAX_MS - SMARTPROXY_DEADLINE_MARGIN_MS
|
|
844
|
-
) {
|
|
769
|
+
if (Date.now() - startedAt > SMARTPROXY_LOCK_POLL_MAX_MS - SMARTPROXY_DEADLINE_MARGIN_MS) {
|
|
845
770
|
break;
|
|
846
771
|
}
|
|
847
|
-
await sleep(
|
|
848
|
-
Math.min(500, Math.max(50, typeof pttl === "number" ? pttl : 100)),
|
|
849
|
-
);
|
|
772
|
+
await sleep(Math.min(500, Math.max(50, typeof pttl === "number" ? pttl : 100)));
|
|
850
773
|
}
|
|
851
774
|
|
|
852
775
|
throw new ProxyResolutionError(
|
|
@@ -893,9 +816,7 @@ function sleep(ms: number, signal?: AbortSignal): Promise<void> {
|
|
|
893
816
|
}
|
|
894
817
|
|
|
895
818
|
function smartproxyAllocatorDeadlineMs(): number {
|
|
896
|
-
return
|
|
897
|
-
smartproxyAllocatorDeadlineMsForTests ?? SMARTPROXY_ALLOCATOR_DEADLINE_MS
|
|
898
|
-
);
|
|
819
|
+
return smartproxyAllocatorDeadlineMsForTests ?? SMARTPROXY_ALLOCATOR_DEADLINE_MS;
|
|
899
820
|
}
|
|
900
821
|
|
|
901
822
|
function createDeadlineAbortController(deadlineAt: number): {
|
|
@@ -917,9 +838,7 @@ function createDeadlineAbortController(deadlineAt: number): {
|
|
|
917
838
|
};
|
|
918
839
|
}
|
|
919
840
|
|
|
920
|
-
function smartproxyAllocatorDeadlineFailure(
|
|
921
|
-
attempt: number,
|
|
922
|
-
): SmartproxyAllocatorFailure {
|
|
841
|
+
function smartproxyAllocatorDeadlineFailure(attempt: number): SmartproxyAllocatorFailure {
|
|
923
842
|
return {
|
|
924
843
|
ok: false,
|
|
925
844
|
attempt,
|
|
@@ -981,22 +900,12 @@ async function allocateAndStoreSmartproxyPool(
|
|
|
981
900
|
},
|
|
982
901
|
): Promise<SmartproxyAllocationResult> {
|
|
983
902
|
const poolSize = resolveSmartproxyPoolSize(policy);
|
|
984
|
-
const allocatorUrl = buildSmartproxyAllocatorUrl(
|
|
985
|
-
policy,
|
|
986
|
-
appKey,
|
|
987
|
-
lifetimeMinutes,
|
|
988
|
-
poolSize,
|
|
989
|
-
);
|
|
903
|
+
const allocatorUrl = buildSmartproxyAllocatorUrl(policy, appKey, lifetimeMinutes, poolSize);
|
|
990
904
|
const allocatorStartedAt = Date.now();
|
|
991
|
-
const allocatorDeadlineAt =
|
|
992
|
-
allocatorStartedAt + smartproxyAllocatorDeadlineMs();
|
|
905
|
+
const allocatorDeadlineAt = allocatorStartedAt + smartproxyAllocatorDeadlineMs();
|
|
993
906
|
let allocation: SmartproxyAllocatorSuccess | undefined;
|
|
994
907
|
let lastFailure: SmartproxyAllocatorFailure | undefined;
|
|
995
|
-
for (
|
|
996
|
-
let attempt = 1;
|
|
997
|
-
attempt <= SMARTPROXY_ALLOCATOR_MAX_ATTEMPTS;
|
|
998
|
-
attempt += 1
|
|
999
|
-
) {
|
|
908
|
+
for (let attempt = 1; attempt <= SMARTPROXY_ALLOCATOR_MAX_ATTEMPTS; attempt += 1) {
|
|
1000
909
|
if (Date.now() >= allocatorDeadlineAt) {
|
|
1001
910
|
lastFailure = smartproxyAllocatorDeadlineFailure(attempt);
|
|
1002
911
|
break;
|
|
@@ -1013,8 +922,7 @@ async function allocateAndStoreSmartproxyPool(
|
|
|
1013
922
|
lastFailure = attemptResult;
|
|
1014
923
|
if (attempt < SMARTPROXY_ALLOCATOR_MAX_ATTEMPTS) {
|
|
1015
924
|
if (Date.now() >= allocatorDeadlineAt) break;
|
|
1016
|
-
const { controller, dispose } =
|
|
1017
|
-
createDeadlineAbortController(allocatorDeadlineAt);
|
|
925
|
+
const { controller, dispose } = createDeadlineAbortController(allocatorDeadlineAt);
|
|
1018
926
|
try {
|
|
1019
927
|
await sleep(smartproxyAllocatorBackoffMs(attempt), controller.signal);
|
|
1020
928
|
} catch {
|
|
@@ -1027,9 +935,7 @@ async function allocateAndStoreSmartproxyPool(
|
|
|
1027
935
|
|
|
1028
936
|
const allocatorMs = Math.max(0, Date.now() - allocatorStartedAt);
|
|
1029
937
|
const allocatorAttempts =
|
|
1030
|
-
allocation?.attempt ??
|
|
1031
|
-
lastFailure?.attempt ??
|
|
1032
|
-
SMARTPROXY_ALLOCATOR_MAX_ATTEMPTS;
|
|
938
|
+
allocation?.attempt ?? lastFailure?.attempt ?? SMARTPROXY_ALLOCATOR_MAX_ATTEMPTS;
|
|
1033
939
|
const allocatorBodyClass =
|
|
1034
940
|
lastFailure?.bodyClass ?? allocation?.bodyClass ?? "usable_proxy_endpoints";
|
|
1035
941
|
const allocatorStatus = lastFailure ? lastFailure.status : allocation?.status;
|
|
@@ -1106,9 +1012,7 @@ async function allocateAndStoreSmartproxyPool(
|
|
|
1106
1012
|
};
|
|
1107
1013
|
}
|
|
1108
1014
|
|
|
1109
|
-
type SmartproxyAllocatorAttemptResult =
|
|
1110
|
-
| SmartproxyAllocatorSuccess
|
|
1111
|
-
| SmartproxyAllocatorFailure;
|
|
1015
|
+
type SmartproxyAllocatorAttemptResult = SmartproxyAllocatorSuccess | SmartproxyAllocatorFailure;
|
|
1112
1016
|
|
|
1113
1017
|
type SmartproxyAllocatorSuccess = {
|
|
1114
1018
|
ok: true;
|
|
@@ -1150,10 +1054,7 @@ async function fetchSmartproxyAllocatorAttempt(
|
|
|
1150
1054
|
|
|
1151
1055
|
let body: string;
|
|
1152
1056
|
try {
|
|
1153
|
-
body = await readSmartproxyAllocatorBodyWithDeadline(
|
|
1154
|
-
response,
|
|
1155
|
-
controller.signal,
|
|
1156
|
-
);
|
|
1057
|
+
body = await readSmartproxyAllocatorBodyWithDeadline(response, controller.signal);
|
|
1157
1058
|
} catch (error) {
|
|
1158
1059
|
dispose();
|
|
1159
1060
|
return {
|
|
@@ -1196,8 +1097,7 @@ async function fetchSmartproxyAllocatorAttempt(
|
|
|
1196
1097
|
}
|
|
1197
1098
|
|
|
1198
1099
|
function smartproxyAllocatorBackoffMs(attempt: number): number {
|
|
1199
|
-
const base =
|
|
1200
|
-
SMARTPROXY_ALLOCATOR_RETRY_BASE_MS * 2 ** Math.max(0, attempt - 1);
|
|
1100
|
+
const base = SMARTPROXY_ALLOCATOR_RETRY_BASE_MS * 2 ** Math.max(0, attempt - 1);
|
|
1201
1101
|
const jitter = Math.floor(Math.random() * SMARTPROXY_ALLOCATOR_RETRY_BASE_MS);
|
|
1202
1102
|
return base + jitter;
|
|
1203
1103
|
}
|
|
@@ -1236,7 +1136,9 @@ function buildSmartproxyAllocatorUrl(
|
|
|
1236
1136
|
if (country) {
|
|
1237
1137
|
params.set("cc", country);
|
|
1238
1138
|
}
|
|
1239
|
-
|
|
1139
|
+
// www.smartproxy.org stopped serving the extraction API on 2026-07-21 (the
|
|
1140
|
+
// old path 404s into the marketing site); the API lives on the api host.
|
|
1141
|
+
return `https://api.smartproxy.org/web_v1/ip/get-ip-v3?${params.toString()}`;
|
|
1240
1142
|
}
|
|
1241
1143
|
|
|
1242
1144
|
function parseSmartproxyAllocatorProxies(body: string): string[] {
|
|
@@ -1247,14 +1149,8 @@ function parseSmartproxyAllocatorProxies(body: string): string[] {
|
|
|
1247
1149
|
|
|
1248
1150
|
try {
|
|
1249
1151
|
const parsed: unknown = JSON.parse(trimmed);
|
|
1250
|
-
const data =
|
|
1251
|
-
|
|
1252
|
-
? parsed.data
|
|
1253
|
-
: undefined;
|
|
1254
|
-
const list =
|
|
1255
|
-
data && typeof data === "object" && "list" in data
|
|
1256
|
-
? data.list
|
|
1257
|
-
: undefined;
|
|
1152
|
+
const data = parsed && typeof parsed === "object" && "data" in parsed ? parsed.data : undefined;
|
|
1153
|
+
const list = data && typeof data === "object" && "list" in data ? data.list : undefined;
|
|
1258
1154
|
if (Array.isArray(list)) {
|
|
1259
1155
|
return list
|
|
1260
1156
|
.map((item) => {
|
|
@@ -1263,8 +1159,7 @@ function parseSmartproxyAllocatorProxies(body: string): string[] {
|
|
|
1263
1159
|
}
|
|
1264
1160
|
const ip = "ip" in item && typeof item.ip === "string" ? item.ip : "";
|
|
1265
1161
|
const port =
|
|
1266
|
-
"port" in item &&
|
|
1267
|
-
(typeof item.port === "string" || typeof item.port === "number")
|
|
1162
|
+
"port" in item && (typeof item.port === "string" || typeof item.port === "number")
|
|
1268
1163
|
? item.port
|
|
1269
1164
|
: "";
|
|
1270
1165
|
return ip && port ? `http://${ip}:${port}` : null;
|
|
@@ -1307,9 +1202,7 @@ export function clearProxyResolutionCache(): void {
|
|
|
1307
1202
|
invalidatedProxyKeys.clear();
|
|
1308
1203
|
}
|
|
1309
1204
|
|
|
1310
|
-
function markSmartproxyCacheInvalidated(
|
|
1311
|
-
options: ProxyResolutionOptions = {},
|
|
1312
|
-
): string | undefined {
|
|
1205
|
+
function markSmartproxyCacheInvalidated(options: ProxyResolutionOptions = {}): string | undefined {
|
|
1313
1206
|
const policy = resolvePolicy(options);
|
|
1314
1207
|
if (!policy || policy.mode === "disabled") {
|
|
1315
1208
|
return undefined;
|
|
@@ -1319,23 +1212,14 @@ function markSmartproxyCacheInvalidated(
|
|
|
1319
1212
|
}
|
|
1320
1213
|
|
|
1321
1214
|
const lifetimeMinutes = resolveSmartproxyLifetime(policy);
|
|
1322
|
-
const cacheKey = buildSmartproxyCacheKey(
|
|
1323
|
-
|
|
1324
|
-
options.affinityKey,
|
|
1325
|
-
lifetimeMinutes,
|
|
1326
|
-
);
|
|
1327
|
-
invalidatedProxyKeys.set(
|
|
1328
|
-
cacheKey,
|
|
1329
|
-
Date.now() + SMARTPROXY_INVALIDATION_SKIP_REDIS_MS,
|
|
1330
|
-
);
|
|
1215
|
+
const cacheKey = buildSmartproxyCacheKey(policy, options.affinityKey, lifetimeMinutes);
|
|
1216
|
+
invalidatedProxyKeys.set(cacheKey, Date.now() + SMARTPROXY_INVALIDATION_SKIP_REDIS_MS);
|
|
1331
1217
|
proxyCache.delete(cacheKey);
|
|
1332
1218
|
proxyInflight.delete(cacheKey);
|
|
1333
1219
|
return cacheKey;
|
|
1334
1220
|
}
|
|
1335
1221
|
|
|
1336
|
-
export function invalidateProxyResolutionCache(
|
|
1337
|
-
options: ProxyResolutionOptions = {},
|
|
1338
|
-
): boolean {
|
|
1222
|
+
export function invalidateProxyResolutionCache(options: ProxyResolutionOptions = {}): boolean {
|
|
1339
1223
|
return markSmartproxyCacheInvalidated(options) !== undefined;
|
|
1340
1224
|
}
|
|
1341
1225
|
|
|
@@ -1374,9 +1258,7 @@ async function importConfig(filePath: string): Promise<ApiFuseConfig | null> {
|
|
|
1374
1258
|
}
|
|
1375
1259
|
}
|
|
1376
1260
|
|
|
1377
|
-
export async function loadApiFuseConfig(
|
|
1378
|
-
dir: string = process.cwd(),
|
|
1379
|
-
): Promise<ApiFuseConfig> {
|
|
1261
|
+
export async function loadApiFuseConfig(dir: string = process.cwd()): Promise<ApiFuseConfig> {
|
|
1380
1262
|
const tsPath = path.resolve(dir, "apifuse.config.ts");
|
|
1381
1263
|
if (existsSync(tsPath)) {
|
|
1382
1264
|
const config = await importConfig(tsPath);
|
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
isRecord,
|
|
7
7
|
type JsonValue,
|
|
8
8
|
toJsonValue,
|
|
9
|
-
} from "./contract-json";
|
|
10
|
-
import type { SchemaLike } from "./types";
|
|
9
|
+
} from "./contract-json.js";
|
|
10
|
+
import type { SchemaLike } from "./types.js";
|
|
11
11
|
|
|
12
12
|
export function describeSchema(schema: SchemaLike): JsonValue {
|
|
13
13
|
if (isZodSchema(schema)) {
|
|
@@ -17,10 +17,7 @@ export function describeSchema(schema: SchemaLike): JsonValue {
|
|
|
17
17
|
vendor: "zod",
|
|
18
18
|
typeName: getSchemaTypeName(schema),
|
|
19
19
|
jsonSchema,
|
|
20
|
-
jsonSchemaHash:
|
|
21
|
-
jsonSchema === undefined
|
|
22
|
-
? undefined
|
|
23
|
-
: digest(canonicalJson(jsonSchema)),
|
|
20
|
+
jsonSchemaHash: jsonSchema === undefined ? undefined : digest(canonicalJson(jsonSchema)),
|
|
24
21
|
});
|
|
25
22
|
}
|
|
26
23
|
const standard = isRecord(schema) ? schema["~standard"] : undefined;
|
|
@@ -30,8 +27,7 @@ export function describeSchema(schema: SchemaLike): JsonValue {
|
|
|
30
27
|
standard: "standard-schema-v1",
|
|
31
28
|
vendor: typeof standard.vendor === "string" ? standard.vendor : "unknown",
|
|
32
29
|
version:
|
|
33
|
-
typeof standard.version === "number" ||
|
|
34
|
-
typeof standard.version === "string"
|
|
30
|
+
typeof standard.version === "number" || typeof standard.version === "string"
|
|
35
31
|
? standard.version
|
|
36
32
|
: undefined,
|
|
37
33
|
});
|
|
@@ -43,9 +39,7 @@ export function describeSchema(schema: SchemaLike): JsonValue {
|
|
|
43
39
|
});
|
|
44
40
|
}
|
|
45
41
|
|
|
46
|
-
export function serializeSmsMatcher(
|
|
47
|
-
value: Record<string, unknown>,
|
|
48
|
-
): Record<string, unknown> {
|
|
42
|
+
export function serializeSmsMatcher(value: Record<string, unknown>): Record<string, unknown> {
|
|
49
43
|
const code = value.code;
|
|
50
44
|
if (!isRecord(code)) return value;
|
|
51
45
|
const pattern = code.pattern;
|
package/src/contract-types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { JsonValue } from "./contract-json";
|
|
2
|
-
import type { ProviderDefinition } from "./types";
|
|
1
|
+
import type { JsonValue } from "./contract-json.js";
|
|
2
|
+
import type { ProviderDefinition } from "./types.js";
|
|
3
3
|
|
|
4
4
|
export const PROVIDER_CONTRACT_SCHEMA_VERSION = "2026-06-23";
|
|
5
5
|
|
package/src/contract.ts
CHANGED
|
@@ -6,13 +6,13 @@ import {
|
|
|
6
6
|
type JsonPrimitive,
|
|
7
7
|
type JsonValue,
|
|
8
8
|
toJsonValue,
|
|
9
|
-
} from "./contract-json";
|
|
10
|
-
import { describeSchema, serializeSmsMatcher } from "./contract-serialization";
|
|
9
|
+
} from "./contract-json.js";
|
|
10
|
+
import { describeSchema, serializeSmsMatcher } from "./contract-serialization.js";
|
|
11
11
|
import {
|
|
12
12
|
PROVIDER_CONTRACT_SCHEMA_VERSION,
|
|
13
13
|
type ProviderContractOperation,
|
|
14
14
|
type ProviderContractSnapshot,
|
|
15
|
-
} from "./contract-types";
|
|
15
|
+
} from "./contract-types.js";
|
|
16
16
|
import type {
|
|
17
17
|
HealthCheckSuite,
|
|
18
18
|
HealthCheckUnsupported,
|
|
@@ -20,7 +20,7 @@ import type {
|
|
|
20
20
|
OperationDefinition,
|
|
21
21
|
OperationTransport,
|
|
22
22
|
ProviderDefinition,
|
|
23
|
-
} from "./types";
|
|
23
|
+
} from "./types.js";
|
|
24
24
|
|
|
25
25
|
export {
|
|
26
26
|
canonicalJson,
|
|
@@ -31,9 +31,7 @@ export {
|
|
|
31
31
|
type ProviderContractSnapshot,
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
-
export function extractProviderContract(
|
|
35
|
-
provider: ProviderDefinition,
|
|
36
|
-
): ProviderContractSnapshot {
|
|
34
|
+
export function extractProviderContract(provider: ProviderDefinition): ProviderContractSnapshot {
|
|
37
35
|
const auth = extractAuth(provider.auth);
|
|
38
36
|
const stealth = toJsonValue(provider.stealth);
|
|
39
37
|
const proxy = toJsonValue(provider.proxy);
|
|
@@ -57,12 +55,8 @@ export function extractProviderContract(
|
|
|
57
55
|
meta: toJsonValue(provider.meta) ?? null,
|
|
58
56
|
operations: Object.entries(provider.operations)
|
|
59
57
|
.sort(([leftId], [rightId]) => leftId.localeCompare(rightId))
|
|
60
|
-
.map(([operationId, operation]) =>
|
|
61
|
-
|
|
62
|
-
),
|
|
63
|
-
...(provider.allowedHosts
|
|
64
|
-
? { allowedHosts: [...provider.allowedHosts].sort() }
|
|
65
|
-
: {}),
|
|
58
|
+
.map(([operationId, operation]) => extractOperation(operationId, operation)),
|
|
59
|
+
...(provider.allowedHosts ? { allowedHosts: [...provider.allowedHosts].sort() } : {}),
|
|
66
60
|
...(stealth === undefined ? {} : { stealth }),
|
|
67
61
|
...(proxy === undefined ? {} : { proxy }),
|
|
68
62
|
...(stt === undefined ? {} : { stt }),
|
|
@@ -78,9 +72,7 @@ export function extractProviderContract(
|
|
|
78
72
|
};
|
|
79
73
|
}
|
|
80
74
|
|
|
81
|
-
export function digestProviderContract(
|
|
82
|
-
snapshot: ProviderContractSnapshot,
|
|
83
|
-
): string {
|
|
75
|
+
export function digestProviderContract(snapshot: ProviderContractSnapshot): string {
|
|
84
76
|
return createHash("sha256").update(canonicalJson(snapshot)).digest("hex");
|
|
85
77
|
}
|
|
86
78
|
|
|
@@ -105,9 +97,7 @@ function extractOperation(
|
|
|
105
97
|
const upstream = toJsonValue(operation.upstream);
|
|
106
98
|
const hints = toJsonValue(operation.hints);
|
|
107
99
|
const healthCheck = extractHealthCheck(operation.healthCheck);
|
|
108
|
-
const healthCheckUnsupported = extractHealthCheckUnsupported(
|
|
109
|
-
operation.healthCheckUnsupported,
|
|
110
|
-
);
|
|
100
|
+
const healthCheckUnsupported = extractHealthCheckUnsupported(operation.healthCheckUnsupported);
|
|
111
101
|
|
|
112
102
|
return {
|
|
113
103
|
id: operationId,
|
|
@@ -149,9 +139,7 @@ function extractAuth(value: ProviderDefinition["auth"]): JsonValue | undefined {
|
|
|
149
139
|
});
|
|
150
140
|
}
|
|
151
141
|
|
|
152
|
-
function extractTransport(
|
|
153
|
-
value: OperationTransport | undefined,
|
|
154
|
-
): JsonValue | undefined {
|
|
142
|
+
function extractTransport(value: OperationTransport | undefined): JsonValue | undefined {
|
|
155
143
|
if (!value) return undefined;
|
|
156
144
|
if (value.kind !== "sse") return toJsonValue(value);
|
|
157
145
|
return compactObject({
|
|
@@ -164,9 +152,7 @@ function extractTransport(
|
|
|
164
152
|
});
|
|
165
153
|
}
|
|
166
154
|
|
|
167
|
-
function extractHealthCheck(
|
|
168
|
-
value: HealthCheckSuite | undefined,
|
|
169
|
-
): JsonValue | undefined {
|
|
155
|
+
function extractHealthCheck(value: HealthCheckSuite | undefined): JsonValue | undefined {
|
|
170
156
|
if (!value) return undefined;
|
|
171
157
|
return compactObject({
|
|
172
158
|
interval: value.interval,
|
|
@@ -204,9 +190,7 @@ function extractHealthJourney(value: HealthJourneyDefinition): JsonValue {
|
|
|
204
190
|
cooldown: value.cooldown,
|
|
205
191
|
smsMatchers: toJsonValue(
|
|
206
192
|
value.smsMatchers?.map((matcher) =>
|
|
207
|
-
serializeSmsMatcher(
|
|
208
|
-
copyRecordWithout(matcher, new Set(["extractOtp"])),
|
|
209
|
-
),
|
|
193
|
+
serializeSmsMatcher(copyRecordWithout(matcher, new Set(["extractOtp"]))),
|
|
210
194
|
),
|
|
211
195
|
),
|
|
212
196
|
requiredSecrets: toJsonValue(value.requiredSecrets),
|